Skip to content

Commit

Permalink
Unrolled build for rust-lang#120400
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rust-timer committed Jan 30, 2024
2 parents c401f09 + fc964fb commit 88a5ece
Show file tree
Hide file tree
Showing 25 changed files with 100 additions and 176 deletions.
32 changes: 21 additions & 11 deletions compiler/rustc_hir_analysis/src/astconv/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::errors::{
use crate::fluent_generated as fluent;
use crate::traits::error_reporting::report_object_safety_error;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{
codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed,
Expand Down Expand Up @@ -463,22 +464,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return err.emit();
}

let mut bound_spans = Vec::new();
let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();

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((tcx.def_span(def.did()), msg)),
ty::Adt(def, _) => {
bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).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((tcx.def_span(tr.def_id), msg.clone()))
bound_spans
.get_mut_or_insert_default(tcx.def_span(tr.def_id))
.push(msg.clone());
}
ty::ExistentialPredicate::Projection(_)
| ty::ExistentialPredicate::AutoTrait(_) => {}
Expand All @@ -487,7 +489,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// 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}`")))
bound_spans
.get_mut_or_insert_default(tcx.def_span(*def_id))
.push(format!("`{quiet}`"));
}
_ => {}
}
Expand Down Expand Up @@ -556,12 +560,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
);

bound_spans.sort();
bound_spans.dedup();
for (span, msg) in bound_spans {
for (span, mut bounds) in bound_spans {
if !tcx.sess.source_map().is_span_accessible(span) {
continue;
}
bounds.sort();
bounds.dedup();
let msg = match &bounds[..] {
[bound] => format!("doesn't satisfy {bound}"),
bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
[bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
[] => unreachable!(),
};
err.span_label(span, msg);
}
add_def_label(&mut err);
Expand Down
69 changes: 47 additions & 22 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::FnCtxt;
use rustc_ast::ast::Mutability;
use rustc_attr::parse_confusables;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{
codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
Expand Down Expand Up @@ -458,22 +459,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

let ty_span = match rcvr_ty.kind() {
let mut ty_span = match rcvr_ty.kind() {
ty::Param(param_type) => {
Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
}
ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
_ => None,
};
if let Some(span) = ty_span {
err.span_label(
span,
format!(
"{item_kind} `{item_name}` not found for this {}",
rcvr_ty.prefix_string(self.tcx)
),
);
}

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

let mut bound_spans = vec![];
let mut bound_spans: SortedMap<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) {
Expand Down Expand Up @@ -641,28 +633,32 @@ 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.get_mut_or_insert_default(tcx.def_span(def.did())).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
.get_mut_or_insert_default(tcx.def_span(tr.def_id))
.push(msg.clone());
}
ty::ExistentialPredicate::Projection(_)
| ty::ExistentialPredicate::AutoTrait(_) => {}
}
}
}
// 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
.get_mut_or_insert_default(tcx.def_span(*def_id))
.push(format!("`{quiet}`"));
}
_ => {}
}
};
Expand Down Expand Up @@ -1169,11 +1165,40 @@ 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() {
for (span, mut bounds) in bound_spans {
if !tcx.sess.source_map().is_span_accessible(span) {
continue;
}
bounds.sort();
bounds.dedup();
let pre = if Some(span) == ty_span {
ty_span.take();
format!(
"{item_kind} `{item_name}` not found for this {} because it ",
rcvr_ty.prefix_string(self.tcx)
)
} else {
String::new()
};
let msg = match &bounds[..] {
[bound] => format!("{pre}doesn't satisfy {bound}"),
bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
[bounds @ .., last] => {
format!("{pre}doesn't satisfy {} or {last}", bounds.join(", "))
}
[] => unreachable!(),
};
err.span_label(span, msg);
}
if let Some(span) = ty_span {
err.span_label(
span,
format!(
"{item_kind} `{item_name}` not found for this {}",
rcvr_ty.prefix_string(self.tcx)
),
);
}

if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ error: the associated type `X` exists for `S<Featureless, Featureless>`, but its
LL | struct S<A, B>(A, B);
| -------------- associated item `X` not found for this struct
LL | struct Featureless;
| ------------------
| |
| doesn't satisfy `Featureless: One`
| doesn't satisfy `Featureless: Two`
| ------------------ doesn't satisfy `Featureless: One` or `Featureless: Two`
...
LL | let _: S::<Featureless, Featureless>::X;
| ^ associated type cannot be referenced on `S<Featureless, Featureless>` due to unsatisfied trait bounds
Expand Down
15 changes: 4 additions & 11 deletions tests/ui/box/unit/unique-object-noncopyable.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
12 changes: 4 additions & 8 deletions tests/ui/box/unit/unique-pinned-nocopy.stderr
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
5 changes: 1 addition & 4 deletions tests/ui/derives/derive-assoc-type-not-impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ error[E0599]: the method `clone` exists for struct `Bar<NotClone>`, but its trai
--> $DIR/derive-assoc-type-not-impl.rs:18:30
|
LL | struct Bar<T: Foo> {
| ------------------
| |
| method `clone` not found for this struct
| doesn't satisfy `Bar<NotClone>: Clone`
| ------------------ method `clone` not found for this struct because it doesn't satisfy `Bar<NotClone>: Clone`
...
LL | struct NotClone;
| --------------- doesn't satisfy `NotClone: Clone`
Expand Down
10 changes: 2 additions & 8 deletions tests/ui/derives/deriving-with-repr-packed-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,10 @@ error[E0599]: the method `clone` exists for struct `Foo<NonCopy>`, but its trait
--> $DIR/deriving-with-repr-packed-2.rs:18:11
|
LL | pub struct Foo<T>(T, T, T);
| -----------------
| |
| method `clone` not found for this struct
| doesn't satisfy `Foo<NonCopy>: Clone`
| ----------------- method `clone` not found for this struct because it 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
Expand Down
25 changes: 4 additions & 21 deletions tests/ui/derives/issue-91550.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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));
| ^^^^^^
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,10 @@ error[E0599]: the size for values of type `Node<i32, RcFamily>` cannot be known
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35
|
LL | enum Node<T, P: PointerFamily> {
| ------------------------------
| |
| variant or associated item `new` not found for this enum
| doesn't satisfy `Node<i32, RcFamily>: Sized`
| ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node<i32, RcFamily>: Sized`
...
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ impl<T: X<Y<i32> = i32>> M for T {}
//~| NOTE

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 method `f` not found for this struct because it doesn't satisfy `<S as X>::Y<i32> = i32` or `S: M`

impl X for S {
type Y<T> = bool;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
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:26: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`
| -------- method `f` not found for this struct because it 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
Expand Down
Loading

0 comments on commit 88a5ece

Please sign in to comment.