Skip to content

Commit 3691ab8

Browse files
committed
Use only one label for multiple unsatisfied bounds on type (astconv)
1 parent 0b77301 commit 3691ab8

File tree

2 files changed

+29
-15
lines changed

2 files changed

+29
-15
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -461,22 +461,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
461461
return err.emit();
462462
}
463463

464-
let mut bound_spans = Vec::new();
464+
let mut bound_spans: FxHashMap<Span, Vec<String>> = Default::default();
465465

466466
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
467-
let msg = format!(
468-
"doesn't satisfy `{}`",
469-
if obligation.len() > 50 { quiet } else { obligation }
470-
);
467+
let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
471468
match &self_ty.kind() {
472469
// Point at the type that couldn't satisfy the bound.
473-
ty::Adt(def, _) => bound_spans.push((tcx.def_span(def.did()), msg)),
470+
ty::Adt(def, _) => {
471+
bound_spans.entry(tcx.def_span(def.did())).or_default().push(msg)
472+
}
474473
// Point at the trait object that couldn't satisfy the bound.
475474
ty::Dynamic(preds, _, _) => {
476475
for pred in preds.iter() {
477476
match pred.skip_binder() {
478477
ty::ExistentialPredicate::Trait(tr) => {
479-
bound_spans.push((tcx.def_span(tr.def_id), msg.clone()))
478+
bound_spans
479+
.entry(tcx.def_span(tr.def_id))
480+
.or_default()
481+
.push(msg.clone());
480482
}
481483
ty::ExistentialPredicate::Projection(_)
482484
| ty::ExistentialPredicate::AutoTrait(_) => {}
@@ -485,7 +487,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
485487
}
486488
// Point at the closure that couldn't satisfy the bound.
487489
ty::Closure(def_id, _) => {
488-
bound_spans.push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`")))
490+
bound_spans
491+
.entry(tcx.def_span(*def_id))
492+
.or_default()
493+
.push(format!("`{quiet}`"));
489494
}
490495
_ => {}
491496
}
@@ -554,12 +559,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
554559
format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
555560
);
556561

557-
bound_spans.sort();
558-
bound_spans.dedup();
559-
for (span, msg) in bound_spans {
562+
let mut bound_spans: Vec<(Span, Vec<String>)> = bound_spans
563+
.into_iter()
564+
.map(|(span, mut bounds)| {
565+
bounds.sort();
566+
bounds.dedup();
567+
(span, bounds)
568+
})
569+
.collect();
570+
bound_spans.sort_by_key(|(span, _)| *span);
571+
for (span, bounds) in bound_spans {
560572
if !tcx.sess.source_map().is_span_accessible(span) {
561573
continue;
562574
}
575+
let msg = match &bounds[..] {
576+
[bound] => format!("doesn't satisfy {bound}"),
577+
[bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
578+
[] => unreachable!(),
579+
};
563580
err.span_label(span, msg);
564581
}
565582
add_def_label(&mut err);

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

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

0 commit comments

Comments
 (0)