about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs48
-rw-r--r--tests/ui/box/unit/unique-object-noncopyable.stderr15
-rw-r--r--tests/ui/box/unit/unique-pinned-nocopy.stderr12
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-2.stderr5
-rw-r--r--tests/ui/derives/issue-91550.stderr25
-rw-r--r--tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr3
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs3
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr5
-rw-r--r--tests/ui/iterators/vec-on-unimplemented.stderr3
-rw-r--r--tests/ui/mismatched_types/issue-36053-2.stderr6
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.stderr16
-rw-r--r--tests/ui/suggestions/mut-borrow-needed-by-trait.stderr3
-rw-r--r--tests/ui/suggestions/suggest-change-mut.stderr3
-rw-r--r--tests/ui/traits/track-obligations.stderr5
-rw-r--r--tests/ui/typeck/derive-sugg-arg-arity.stderr3
-rw-r--r--tests/ui/typeck/issue-31173.stderr6
16 files changed, 56 insertions, 105 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0b8a25eedaf..d7a0565895d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -9,7 +9,7 @@ use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
 use rustc_attr::parse_confusables;
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::StashKey;
 use rustc_errors::{
@@ -547,7 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
         }
 
-        let mut bound_spans = vec![];
+        let mut bound_spans: FxHashMap<Span, Vec<String>> = Default::default();
         let mut restrict_type_params = false;
         let mut unsatisfied_bounds = false;
         if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
@@ -642,19 +642,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     false
                 };
             let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
-                let msg = format!(
-                    "doesn't satisfy `{}`",
-                    if obligation.len() > 50 { quiet } else { obligation }
-                );
+                let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
                 match &self_ty.kind() {
                     // Point at the type that couldn't satisfy the bound.
-                    ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
+                    ty::Adt(def, _) => {
+                        bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg)
+                    }
                     // Point at the trait object that couldn't satisfy the bound.
                     ty::Dynamic(preds, _, _) => {
                         for pred in preds.iter() {
                             match pred.skip_binder() {
                                 ty::ExistentialPredicate::Trait(tr) => {
-                                    bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
+                                    bound_spans
+                                        .entry(tcx.def_span(tr.def_id))
+                                        .or_default()
+                                        .push(msg.clone());
                                 }
                                 ty::ExistentialPredicate::Projection(_)
                                 | ty::ExistentialPredicate::AutoTrait(_) => {}
@@ -662,8 +664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     // Point at the closure that couldn't satisfy the bound.
-                    ty::Closure(def_id, _) => bound_spans
-                        .push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`"))),
+                    ty::Closure(def_id, _) => {
+                        bound_spans
+                            .entry(tcx.def_span(*def_id))
+                            .or_default()
+                            .push(format!("`{quiet}`"));
+                    }
                     _ => {}
                 }
             };
@@ -1170,9 +1176,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name);
 
-        bound_spans.sort();
-        bound_spans.dedup();
-        for (span, msg) in bound_spans.into_iter() {
+        #[allow(rustc::potential_query_instability)] // We immediately sort the resulting Vec.
+        let mut bound_spans: Vec<(Span, Vec<String>)> = bound_spans
+            .into_iter()
+            .map(|(span, mut bounds)| {
+                bounds.sort();
+                bounds.dedup();
+                (span, bounds)
+            })
+            .collect();
+        bound_spans.sort_by_key(|(span, _)| *span);
+        for (span, bounds) in bound_spans {
+            if !tcx.sess.source_map().is_span_accessible(span) {
+                continue;
+            }
+            let msg = match &bounds[..] {
+                [bound] => format!("doesn't satisfy {bound}"),
+                [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
+                [] => unreachable!(),
+            };
             err.span_label(span, msg);
         }
 
diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr
index 1b98d09ccdd..49547872d1a 100644
--- a/tests/ui/box/unit/unique-object-noncopyable.stderr
+++ b/tests/ui/box/unit/unique-object-noncopyable.stderr
@@ -1,18 +1,11 @@
 error[E0599]: the method `clone` exists for struct `Box<dyn Foo>`, but its trait bounds were not satisfied
   --> $DIR/unique-object-noncopyable.rs:24:16
    |
-LL |   trait Foo {
-   |   ---------
-   |   |
-   |   doesn't satisfy `dyn Foo: Clone`
-   |   doesn't satisfy `dyn Foo: Sized`
+LL | trait Foo {
+   | --------- doesn't satisfy `dyn Foo: Clone` or `dyn Foo: Sized`
 ...
-LL |       let _z = y.clone();
-   |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-  ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-   = note: doesn't satisfy `Box<dyn Foo>: Clone`
+LL |     let _z = y.clone();
+   |                ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `dyn Foo: Sized`
diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr
index d662a2d6d05..d2bf72249c4 100644
--- a/tests/ui/box/unit/unique-pinned-nocopy.stderr
+++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr
@@ -1,15 +1,11 @@
 error[E0599]: the method `clone` exists for struct `Box<R>`, but its trait bounds were not satisfied
   --> $DIR/unique-pinned-nocopy.rs:12:16
    |
-LL |   struct R {
-   |   -------- doesn't satisfy `R: Clone`
+LL | struct R {
+   | -------- doesn't satisfy `R: Clone`
 ...
-LL |       let _j = i.clone();
-   |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-  ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-   = note: doesn't satisfy `Box<R>: Clone`
+LL |     let _j = i.clone();
+   |                ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `R: Clone`
diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr
index 0eaca7e2360..172dd80fe1d 100644
--- a/tests/ui/derives/deriving-with-repr-packed-2.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr
@@ -8,10 +8,7 @@ LL | pub struct Foo<T>(T, T, T);
    | doesn't satisfy `Foo<NonCopy>: Clone`
 LL |
 LL | struct NonCopy;
-   | --------------
-   | |
-   | doesn't satisfy `NonCopy: Clone`
-   | doesn't satisfy `NonCopy: Copy`
+   | -------------- doesn't satisfy `NonCopy: Clone` or `NonCopy: Copy`
 ...
 LL |     _ = x.clone();
    |           ^^^^^ method cannot be called on `Foo<NonCopy>` due to unsatisfied trait bounds
diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr
index 1324b80b5fc..9e171896718 100644
--- a/tests/ui/derives/issue-91550.stderr
+++ b/tests/ui/derives/issue-91550.stderr
@@ -2,11 +2,7 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
   --> $DIR/issue-91550.rs:8:8
    |
 LL | struct Value(u32);
-   | ------------
-   | |
-   | doesn't satisfy `Value: Eq`
-   | doesn't satisfy `Value: Hash`
-   | doesn't satisfy `Value: PartialEq`
+   | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
 ...
 LL |     hs.insert(Value(0));
    |        ^^^^^^
@@ -26,10 +22,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
   --> $DIR/issue-91550.rs:26:9
    |
 LL | pub struct NoDerives;
-   | --------------------
-   | |
-   | doesn't satisfy `NoDerives: Eq`
-   | doesn't satisfy `NoDerives: PartialEq`
+   | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_eq` not found for this struct
@@ -57,12 +50,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
   --> $DIR/issue-91550.rs:27:9
    |
 LL | pub struct NoDerives;
-   | --------------------
-   | |
-   | doesn't satisfy `NoDerives: Eq`
-   | doesn't satisfy `NoDerives: Ord`
-   | doesn't satisfy `NoDerives: PartialEq`
-   | doesn't satisfy `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord` not found for this struct
@@ -94,12 +82,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
   --> $DIR/issue-91550.rs:28:9
    |
 LL | pub struct NoDerives;
-   | --------------------
-   | |
-   | doesn't satisfy `NoDerives: Eq`
-   | doesn't satisfy `NoDerives: Ord`
-   | doesn't satisfy `NoDerives: PartialEq`
-   | doesn't satisfy `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord_and_partial_ord` not found for this struct
diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr
index 3a973d356dc..2ce10ce9c1c 100644
--- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr
+++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr
@@ -26,9 +26,6 @@ LL | enum Node<T, P: PointerFamily> {
 ...
 LL |     let mut list = RcNode::<i32>::new();
    |                                   ^^^ doesn't have a size known at compile-time
-  --> $SRC_DIR/core/src/ops/deref.rs:LL:COL
-   |
-   = note: doesn't satisfy `_: Sized`
    |
 note: trait bound `Node<i32, RcFamily>: Sized` was not satisfied
   --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18
diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
index 83655341d6a..1f9e4f24b16 100644
--- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
@@ -17,8 +17,7 @@ impl<T: X<Y<i32> = i32>> M for T {}
 
 struct S;
 //~^ NOTE method `f` not found for this
-//~| NOTE doesn't satisfy `<S as X>::Y<i32> = i32`
-//~| NOTE doesn't satisfy `S: M`
+//~| NOTE doesn't satisfy `<S as X>::Y<i32> = i32` or `S: M`
 
 impl X for S {
     type Y<T> = bool;
diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
index 7ca0b2912a6..489b2772ad8 100644
--- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
@@ -1,12 +1,11 @@
 error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
-  --> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7
+  --> $DIR/method-unsatisfied-assoc-type-predicate.rs:27:7
    |
 LL | struct S;
    | --------
    | |
    | method `f` not found for this struct
-   | doesn't satisfy `<S as X>::Y<i32> = i32`
-   | doesn't satisfy `S: M`
+   | doesn't satisfy `<S as X>::Y<i32> = i32` or `S: M`
 ...
 LL |     a.f();
    |       ^ method cannot be called on `S` due to unsatisfied trait bounds
diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr
index e2a80dbffde..29b19d5e3b4 100644
--- a/tests/ui/iterators/vec-on-unimplemented.stderr
+++ b/tests/ui/iterators/vec-on-unimplemented.stderr
@@ -3,9 +3,6 @@ error[E0599]: `Vec<bool>` is not an iterator
    |
 LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
    |                       ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-   = note: doesn't satisfy `Vec<bool>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<bool>: Iterator`
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index 292525daa3d..6d23319ca7e 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -21,11 +21,7 @@ error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, {cl
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                       ---------       ^^^^^ method cannot be called due to unsatisfied trait bounds
    |                                       |
-   |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
-   |                                       doesn't satisfy `_: FnMut<(&&str,)>`
-  --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
-   |
-   = note: doesn't satisfy `_: Iterator`
+   |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>`
    |
    = note: the following trait bounds were not satisfied:
            `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool`
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr
index e2db0da74f0..9d6d29ec74e 100644
--- a/tests/ui/suggestions/derive-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr
@@ -2,10 +2,7 @@ error[E0599]: the method `test` exists for struct `Foo<Enum, CloneEnum>`, but it
   --> $DIR/derive-trait-for-method-call.rs:28:15
    |
 LL | enum Enum {
-   | ---------
-   | |
-   | doesn't satisfy `Enum: Clone`
-   | doesn't satisfy `Enum: Default`
+   | --------- doesn't satisfy `Enum: Clone` or `Enum: Default`
 ...
 LL | enum CloneEnum {
    | -------------- doesn't satisfy `CloneEnum: Default`
@@ -40,10 +37,7 @@ error[E0599]: the method `test` exists for struct `Foo<Struct, CloneStruct>`, bu
   --> $DIR/derive-trait-for-method-call.rs:34:15
    |
 LL | struct Struct {
-   | -------------
-   | |
-   | doesn't satisfy `Struct: Clone`
-   | doesn't satisfy `Struct: Default`
+   | ------------- doesn't satisfy `Struct: Clone` or `Struct: Default`
 ...
 LL | struct CloneStruct {
    | ------------------ doesn't satisfy `CloneStruct: Default`
@@ -85,12 +79,6 @@ LL | struct Foo<X, Y> (X, Y);
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
-  --> $SRC_DIR/std/src/time.rs:LL:COL
-   |
-   = note: doesn't satisfy `Instant: Default`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-   = note: doesn't satisfy `Vec<Enum>: Clone`
    |
 note: the following trait bounds were not satisfied:
       `Instant: Default`
diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
index 94710f4503f..09a9b1d3b34 100644
--- a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -25,9 +25,6 @@ error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`,
    |
 LL |     writeln!(fp, "hello world").unwrap();
    |     ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
-  --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-   = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
    |
 note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
   --> $DIR/mut-borrow-needed-by-trait.rs:21:14
diff --git a/tests/ui/suggestions/suggest-change-mut.stderr b/tests/ui/suggestions/suggest-change-mut.stderr
index d194afeaf93..216d1e810fd 100644
--- a/tests/ui/suggestions/suggest-change-mut.stderr
+++ b/tests/ui/suggestions/suggest-change-mut.stderr
@@ -27,9 +27,6 @@ error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its
    |
 LL |         stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
    |                       ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
-  --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-   = note: doesn't satisfy `BufReader<&T>: BufRead`
    |
    = note: the following trait bounds were not satisfied:
            `&T: std::io::Read`
diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr
index 89477475970..822fc91e43f 100644
--- a/tests/ui/traits/track-obligations.stderr
+++ b/tests/ui/traits/track-obligations.stderr
@@ -2,10 +2,7 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b
   --> $DIR/track-obligations.rs:83:16
    |
 LL | struct ALayer<C>(C);
-   | ----------------
-   | |
-   | doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service`
-   | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+   | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>`
 ...
 LL | struct Client<C>(C);
    | ---------------- method `check` not found for this struct
diff --git a/tests/ui/typeck/derive-sugg-arg-arity.stderr b/tests/ui/typeck/derive-sugg-arg-arity.stderr
index 41b16a772ca..46421ba942c 100644
--- a/tests/ui/typeck/derive-sugg-arg-arity.stderr
+++ b/tests/ui/typeck/derive-sugg-arg-arity.stderr
@@ -5,8 +5,7 @@ LL | pub struct A;
    | ------------
    | |
    | function or associated item `partial_cmp` not found for this struct
-   | doesn't satisfy `A: Iterator`
-   | doesn't satisfy `A: PartialOrd<_>`
+   | doesn't satisfy `A: Iterator` or `A: PartialOrd<_>`
 ...
 LL |         _ => match A::partial_cmp() {},
    |                       ^^^^^^^^^^^ function or associated item cannot be called on `A` due to unsatisfied trait bounds
diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr
index d65c4306a5f..0983147a5f0 100644
--- a/tests/ui/typeck/issue-31173.stderr
+++ b/tests/ui/typeck/issue-31173.stderr
@@ -35,12 +35,6 @@ LL | |         .collect();
    | |         -^^^^^^^ method cannot be called due to unsatisfied trait bounds
    | |_________|
    | 
-  --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
-   |
-   = note: doesn't satisfy `<_ as Iterator>::Item = &_`
-  --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
-   |
-   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_`