Skip to content

Commit 88a5ece

Browse files
authored
Unrolled build for rust-lang#120400
Rollup merge of rust-lang#120400 - estebank:bound-error-cleanup, r=oli-obk Bound errors span label cleanup Consolidate span labels for "this type doesn't satisfy a bound" for more compact diagnostic output.
2 parents c401f09 + fc964fb commit 88a5ece

25 files changed

+100
-176
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::errors::{
66
use crate::fluent_generated as fluent;
77
use crate::traits::error_reporting::report_object_safety_error;
88
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
9+
use rustc_data_structures::sorted_map::SortedMap;
910
use rustc_data_structures::unord::UnordMap;
1011
use rustc_errors::{
1112
codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed,
@@ -463,22 +464,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
463464
return err.emit();
464465
}
465466

466-
let mut bound_spans = Vec::new();
467+
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
467468

468469
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
469-
let msg = format!(
470-
"doesn't satisfy `{}`",
471-
if obligation.len() > 50 { quiet } else { obligation }
472-
);
470+
let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
473471
match &self_ty.kind() {
474472
// Point at the type that couldn't satisfy the bound.
475-
ty::Adt(def, _) => bound_spans.push((tcx.def_span(def.did()), msg)),
473+
ty::Adt(def, _) => {
474+
bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
475+
}
476476
// Point at the trait object that couldn't satisfy the bound.
477477
ty::Dynamic(preds, _, _) => {
478478
for pred in preds.iter() {
479479
match pred.skip_binder() {
480480
ty::ExistentialPredicate::Trait(tr) => {
481-
bound_spans.push((tcx.def_span(tr.def_id), msg.clone()))
481+
bound_spans
482+
.get_mut_or_insert_default(tcx.def_span(tr.def_id))
483+
.push(msg.clone());
482484
}
483485
ty::ExistentialPredicate::Projection(_)
484486
| ty::ExistentialPredicate::AutoTrait(_) => {}
@@ -487,7 +489,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
487489
}
488490
// Point at the closure that couldn't satisfy the bound.
489491
ty::Closure(def_id, _) => {
490-
bound_spans.push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`")))
492+
bound_spans
493+
.get_mut_or_insert_default(tcx.def_span(*def_id))
494+
.push(format!("`{quiet}`"));
491495
}
492496
_ => {}
493497
}
@@ -556,12 +560,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
556560
format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
557561
);
558562

559-
bound_spans.sort();
560-
bound_spans.dedup();
561-
for (span, msg) in bound_spans {
563+
for (span, mut bounds) in bound_spans {
562564
if !tcx.sess.source_map().is_span_accessible(span) {
563565
continue;
564566
}
567+
bounds.sort();
568+
bounds.dedup();
569+
let msg = match &bounds[..] {
570+
[bound] => format!("doesn't satisfy {bound}"),
571+
bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
572+
[bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
573+
[] => unreachable!(),
574+
};
565575
err.span_label(span, msg);
566576
}
567577
add_def_label(&mut err);

compiler/rustc_hir_typeck/src/method/suggest.rs

+47-22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::FnCtxt;
99
use rustc_ast::ast::Mutability;
1010
use rustc_attr::parse_confusables;
1111
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
12+
use rustc_data_structures::sorted_map::SortedMap;
1213
use rustc_data_structures::unord::UnordSet;
1314
use rustc_errors::{
1415
codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
@@ -458,22 +459,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
458459
);
459460
}
460461

461-
let ty_span = match rcvr_ty.kind() {
462+
let mut ty_span = match rcvr_ty.kind() {
462463
ty::Param(param_type) => {
463464
Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
464465
}
465466
ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
466467
_ => None,
467468
};
468-
if let Some(span) = ty_span {
469-
err.span_label(
470-
span,
471-
format!(
472-
"{item_kind} `{item_name}` not found for this {}",
473-
rcvr_ty.prefix_string(self.tcx)
474-
),
475-
);
476-
}
477469

478470
if let SelfSource::MethodCall(rcvr_expr) = source {
479471
self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
@@ -546,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
546538
);
547539
}
548540

549-
let mut bound_spans = vec![];
541+
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
550542
let mut restrict_type_params = false;
551543
let mut unsatisfied_bounds = false;
552544
if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
@@ -641,28 +633,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
641633
false
642634
};
643635
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
644-
let msg = format!(
645-
"doesn't satisfy `{}`",
646-
if obligation.len() > 50 { quiet } else { obligation }
647-
);
636+
let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
648637
match &self_ty.kind() {
649638
// Point at the type that couldn't satisfy the bound.
650-
ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
639+
ty::Adt(def, _) => {
640+
bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
641+
}
651642
// Point at the trait object that couldn't satisfy the bound.
652643
ty::Dynamic(preds, _, _) => {
653644
for pred in preds.iter() {
654645
match pred.skip_binder() {
655646
ty::ExistentialPredicate::Trait(tr) => {
656-
bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
647+
bound_spans
648+
.get_mut_or_insert_default(tcx.def_span(tr.def_id))
649+
.push(msg.clone());
657650
}
658651
ty::ExistentialPredicate::Projection(_)
659652
| ty::ExistentialPredicate::AutoTrait(_) => {}
660653
}
661654
}
662655
}
663656
// Point at the closure that couldn't satisfy the bound.
664-
ty::Closure(def_id, _) => bound_spans
665-
.push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`"))),
657+
ty::Closure(def_id, _) => {
658+
bound_spans
659+
.get_mut_or_insert_default(tcx.def_span(*def_id))
660+
.push(format!("`{quiet}`"));
661+
}
666662
_ => {}
667663
}
668664
};
@@ -1169,11 +1165,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11691165

11701166
self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name);
11711167

1172-
bound_spans.sort();
1173-
bound_spans.dedup();
1174-
for (span, msg) in bound_spans.into_iter() {
1168+
for (span, mut bounds) in bound_spans {
1169+
if !tcx.sess.source_map().is_span_accessible(span) {
1170+
continue;
1171+
}
1172+
bounds.sort();
1173+
bounds.dedup();
1174+
let pre = if Some(span) == ty_span {
1175+
ty_span.take();
1176+
format!(
1177+
"{item_kind} `{item_name}` not found for this {} because it ",
1178+
rcvr_ty.prefix_string(self.tcx)
1179+
)
1180+
} else {
1181+
String::new()
1182+
};
1183+
let msg = match &bounds[..] {
1184+
[bound] => format!("{pre}doesn't satisfy {bound}"),
1185+
bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
1186+
[bounds @ .., last] => {
1187+
format!("{pre}doesn't satisfy {} or {last}", bounds.join(", "))
1188+
}
1189+
[] => unreachable!(),
1190+
};
11751191
err.span_label(span, msg);
11761192
}
1193+
if let Some(span) = ty_span {
1194+
err.span_label(
1195+
span,
1196+
format!(
1197+
"{item_kind} `{item_name}` not found for this {}",
1198+
rcvr_ty.prefix_string(self.tcx)
1199+
),
1200+
);
1201+
}
11771202

11781203
if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
11791204
} else {

tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ error: the associated type `X` exists for `S<Featureless, Featureless>`, but its
44
LL | struct S<A, B>(A, B);
55
| -------------- associated item `X` not found for this struct
66
LL | struct Featureless;
7-
| ------------------
8-
| |
9-
| doesn't satisfy `Featureless: One`
10-
| doesn't satisfy `Featureless: Two`
7+
| ------------------ doesn't satisfy `Featureless: One` or `Featureless: Two`
118
...
129
LL | let _: S::<Featureless, Featureless>::X;
1310
| ^ associated type cannot be referenced on `S<Featureless, Featureless>` due to unsatisfied trait bounds

tests/ui/box/unit/unique-object-noncopyable.stderr

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
error[E0599]: the method `clone` exists for struct `Box<dyn Foo>`, but its trait bounds were not satisfied
22
--> $DIR/unique-object-noncopyable.rs:24:16
33
|
4-
LL | trait Foo {
5-
| ---------
6-
| |
7-
| doesn't satisfy `dyn Foo: Clone`
8-
| doesn't satisfy `dyn Foo: Sized`
4+
LL | trait Foo {
5+
| --------- doesn't satisfy `dyn Foo: Clone` or `dyn Foo: Sized`
96
...
10-
LL | let _z = y.clone();
11-
| ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
12-
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
13-
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
14-
|
15-
= note: doesn't satisfy `Box<dyn Foo>: Clone`
7+
LL | let _z = y.clone();
8+
| ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
169
|
1710
= note: the following trait bounds were not satisfied:
1811
`dyn Foo: Sized`

tests/ui/box/unit/unique-pinned-nocopy.stderr

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
error[E0599]: the method `clone` exists for struct `Box<R>`, but its trait bounds were not satisfied
22
--> $DIR/unique-pinned-nocopy.rs:12:16
33
|
4-
LL | struct R {
5-
| -------- doesn't satisfy `R: Clone`
4+
LL | struct R {
5+
| -------- doesn't satisfy `R: Clone`
66
...
7-
LL | let _j = i.clone();
8-
| ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
9-
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
10-
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
11-
|
12-
= note: doesn't satisfy `Box<R>: Clone`
7+
LL | let _j = i.clone();
8+
| ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
139
|
1410
= note: the following trait bounds were not satisfied:
1511
`R: Clone`

tests/ui/derives/derive-assoc-type-not-impl.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ error[E0599]: the method `clone` exists for struct `Bar<NotClone>`, but its trai
22
--> $DIR/derive-assoc-type-not-impl.rs:18:30
33
|
44
LL | struct Bar<T: Foo> {
5-
| ------------------
6-
| |
7-
| method `clone` not found for this struct
8-
| doesn't satisfy `Bar<NotClone>: Clone`
5+
| ------------------ method `clone` not found for this struct because it doesn't satisfy `Bar<NotClone>: Clone`
96
...
107
LL | struct NotClone;
118
| --------------- doesn't satisfy `NotClone: Clone`

tests/ui/derives/deriving-with-repr-packed-2.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@ error[E0599]: the method `clone` exists for struct `Foo<NonCopy>`, but its trait
22
--> $DIR/deriving-with-repr-packed-2.rs:18:11
33
|
44
LL | pub struct Foo<T>(T, T, T);
5-
| -----------------
6-
| |
7-
| method `clone` not found for this struct
8-
| doesn't satisfy `Foo<NonCopy>: Clone`
5+
| ----------------- method `clone` not found for this struct because it doesn't satisfy `Foo<NonCopy>: Clone`
96
LL |
107
LL | struct NonCopy;
11-
| --------------
12-
| |
13-
| doesn't satisfy `NonCopy: Clone`
14-
| doesn't satisfy `NonCopy: Copy`
8+
| -------------- doesn't satisfy `NonCopy: Clone` or `NonCopy: Copy`
159
...
1610
LL | _ = x.clone();
1711
| ^^^^^ method cannot be called on `Foo<NonCopy>` due to unsatisfied trait bounds

tests/ui/derives/issue-91550.stderr

+4-21
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
22
--> $DIR/issue-91550.rs:8:8
33
|
44
LL | struct Value(u32);
5-
| ------------
6-
| |
7-
| doesn't satisfy `Value: Eq`
8-
| doesn't satisfy `Value: Hash`
9-
| doesn't satisfy `Value: PartialEq`
5+
| ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
106
...
117
LL | hs.insert(Value(0));
128
| ^^^^^^
@@ -26,10 +22,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
2622
--> $DIR/issue-91550.rs:26:9
2723
|
2824
LL | pub struct NoDerives;
29-
| --------------------
30-
| |
31-
| doesn't satisfy `NoDerives: Eq`
32-
| doesn't satisfy `NoDerives: PartialEq`
25+
| -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
3326
LL |
3427
LL | struct Object<T>(T);
3528
| ---------------- 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
5750
--> $DIR/issue-91550.rs:27:9
5851
|
5952
LL | pub struct NoDerives;
60-
| --------------------
61-
| |
62-
| doesn't satisfy `NoDerives: Eq`
63-
| doesn't satisfy `NoDerives: Ord`
64-
| doesn't satisfy `NoDerives: PartialEq`
65-
| doesn't satisfy `NoDerives: PartialOrd`
53+
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
6654
LL |
6755
LL | struct Object<T>(T);
6856
| ---------------- 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
9482
--> $DIR/issue-91550.rs:28:9
9583
|
9684
LL | pub struct NoDerives;
97-
| --------------------
98-
| |
99-
| doesn't satisfy `NoDerives: Eq`
100-
| doesn't satisfy `NoDerives: Ord`
101-
| doesn't satisfy `NoDerives: PartialEq`
102-
| doesn't satisfy `NoDerives: PartialOrd`
85+
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
10386
LL |
10487
LL | struct Object<T>(T);
10588
| ---------------- method `use_ord_and_partial_ord` not found for this struct

tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,10 @@ error[E0599]: the size for values of type `Node<i32, RcFamily>` cannot be known
1919
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35
2020
|
2121
LL | enum Node<T, P: PointerFamily> {
22-
| ------------------------------
23-
| |
24-
| variant or associated item `new` not found for this enum
25-
| doesn't satisfy `Node<i32, RcFamily>: Sized`
22+
| ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node<i32, RcFamily>: Sized`
2623
...
2724
LL | let mut list = RcNode::<i32>::new();
2825
| ^^^ doesn't have a size known at compile-time
29-
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
30-
|
31-
= note: doesn't satisfy `_: Sized`
3226
|
3327
note: trait bound `Node<i32, RcFamily>: Sized` was not satisfied
3428
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18

tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ impl<T: X<Y<i32> = i32>> M for T {}
1616
//~| NOTE
1717

1818
struct S;
19-
//~^ NOTE method `f` not found for this
20-
//~| NOTE doesn't satisfy `<S as X>::Y<i32> = i32`
21-
//~| NOTE doesn't satisfy `S: M`
19+
//~^ NOTE method `f` not found for this struct because it doesn't satisfy `<S as X>::Y<i32> = i32` or `S: M`
2220

2321
impl X for S {
2422
type Y<T> = bool;

tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
2-
--> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7
2+
--> $DIR/method-unsatisfied-assoc-type-predicate.rs:26:7
33
|
44
LL | struct S;
5-
| --------
6-
| |
7-
| method `f` not found for this struct
8-
| doesn't satisfy `<S as X>::Y<i32> = i32`
9-
| doesn't satisfy `S: M`
5+
| -------- method `f` not found for this struct because it doesn't satisfy `<S as X>::Y<i32> = i32` or `S: M`
106
...
117
LL | a.f();
128
| ^ method cannot be called on `S` due to unsatisfied trait bounds

0 commit comments

Comments
 (0)