Skip to content

Commit 3f2a63a

Browse files
committed
Use trait name instead of full constraint in suggestion message
``` help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) { | ++++++++++++++ ``` ``` help: consider restricting type parameter `V` with trait `Copy` | LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V { | +++++++++++++++++++ ```
1 parent 568b0ac commit 3f2a63a

File tree

99 files changed

+229
-191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+229
-191
lines changed

compiler/rustc_middle/src/ty/diagnostics.rs

+61-23
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use std::fmt::Write;
44
use std::ops::ControlFlow;
55

66
use rustc_data_structures::fx::FxHashMap;
7-
use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display};
7+
use rustc_errors::{
8+
Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize,
9+
};
810
use rustc_hir::def::DefKind;
911
use rustc_hir::def_id::DefId;
1012
use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind};
@@ -288,7 +290,11 @@ pub fn suggest_constraining_type_params<'a>(
288290
None => true,
289291
};
290292
if stable || tcx.sess.is_nightly_build() {
291-
grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id));
293+
grouped.entry(param_name).or_insert(Vec::new()).push((
294+
constraint,
295+
def_id,
296+
if stable { "" } else { "unstable " },
297+
));
292298
if !stable {
293299
unstable_suggestion = true;
294300
}
@@ -303,10 +309,10 @@ pub fn suggest_constraining_type_params<'a>(
303309
let Some(param) = param else { return false };
304310

305311
{
306-
let mut sized_constraints = constraints.extract_if(|(_, def_id)| {
312+
let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| {
307313
def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
308314
});
309-
if let Some((_, def_id)) = sized_constraints.next() {
315+
if let Some((_, def_id, _)) = sized_constraints.next() {
310316
applicability = Applicability::MaybeIncorrect;
311317

312318
err.span_label(param.span, "this type parameter needs to be `Sized`");
@@ -325,15 +331,52 @@ pub fn suggest_constraining_type_params<'a>(
325331
.collect();
326332

327333
constraints
328-
.retain(|(_, def_id)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def)));
334+
.retain(|(_, def_id, _)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def)));
329335

330336
if constraints.is_empty() {
331337
continue;
332338
}
333339

334-
let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
340+
let mut constraint = constraints.iter().map(|&(c, _, _)| c).collect::<Vec<_>>();
335341
constraint.sort();
336342
constraint.dedup();
343+
let all_stable = constraints.iter().all(|&(_, _, stable)| stable.is_empty());
344+
let all_unstable = constraints.iter().all(|&(_, _, stable)| !stable.is_empty());
345+
let post = if all_stable || all_unstable {
346+
// Don't redundantly say "trait `X`, trait `Y`", instead "traits `X` and `Y`"
347+
let mut trait_names = constraints
348+
.iter()
349+
.map(|&(c, def_id, _)| match def_id {
350+
None => format!("`{c}`"),
351+
Some(def_id) => format!("`{}`", tcx.item_name(def_id)),
352+
})
353+
.collect::<Vec<_>>();
354+
trait_names.sort();
355+
trait_names.dedup();
356+
let n = trait_names.len();
357+
let stable = if all_stable { "" } else { "unstable " };
358+
format!("{stable}trait{} {}", pluralize!(n), match &trait_names[..] {
359+
[t] => t.to_string(),
360+
[ts @ .., last] => format!("{} and {last}", ts.join(", ")),
361+
[] => return false,
362+
},)
363+
} else {
364+
// We're more explicit when there's a mix of stable and unstable traits.
365+
let mut trait_names = constraints
366+
.iter()
367+
.map(|&(c, def_id, stable)| match def_id {
368+
None => format!("{stable}trait `{c}`"),
369+
Some(def_id) => format!("{stable}trait `{}`", tcx.item_name(def_id)),
370+
})
371+
.collect::<Vec<_>>();
372+
trait_names.sort();
373+
trait_names.dedup();
374+
match &trait_names[..] {
375+
[t] => t.to_string(),
376+
[ts @ .., last] => format!("{} and {last}", ts.join(", ")),
377+
[] => return false,
378+
}
379+
};
337380
let constraint = constraint.join(" + ");
338381
let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| {
339382
let suggestion = if span_to_replace.is_some() {
@@ -351,18 +394,18 @@ pub fn suggest_constraining_type_params<'a>(
351394
if let Some(open_paren_sp) = open_paren_sp {
352395
suggestions.push((
353396
open_paren_sp,
354-
constraint.clone(),
397+
post.clone(),
355398
"(".to_string(),
356399
RestrictBoundFurther,
357400
));
358401
suggestions.push((
359402
span,
360-
constraint.clone(),
403+
post.clone(),
361404
format!("){suggestion}"),
362405
RestrictBoundFurther,
363406
));
364407
} else {
365-
suggestions.push((span, constraint.clone(), suggestion, RestrictBoundFurther));
408+
suggestions.push((span, post.clone(), suggestion, RestrictBoundFurther));
366409
}
367410
};
368411

@@ -420,8 +463,8 @@ pub fn suggest_constraining_type_params<'a>(
420463
// - insert: `, X: Bar`
421464
suggestions.push((
422465
generics.tail_span_for_predicate_suggestion(),
423-
constraint.clone(),
424-
constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
466+
post,
467+
constraints.iter().fold(String::new(), |mut string, &(constraint, _, _)| {
425468
write!(string, ", {param_name}: {constraint}").unwrap();
426469
string
427470
}),
@@ -450,7 +493,7 @@ pub fn suggest_constraining_type_params<'a>(
450493
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
451494
suggestions.push((
452495
generics.tail_span_for_predicate_suggestion(),
453-
constraint.clone(),
496+
post,
454497
format!("{where_prefix} {param_name}: {constraint}"),
455498
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
456499
));
@@ -464,7 +507,7 @@ pub fn suggest_constraining_type_params<'a>(
464507
if let Some(colon_span) = param.colon_span {
465508
suggestions.push((
466509
colon_span.shrink_to_hi(),
467-
constraint.clone(),
510+
post,
468511
format!(" {constraint}"),
469512
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
470513
));
@@ -477,7 +520,7 @@ pub fn suggest_constraining_type_params<'a>(
477520
// - help: consider restricting this type parameter with `T: Foo`
478521
suggestions.push((
479522
param.span.shrink_to_hi(),
480-
constraint.clone(),
523+
post,
481524
format!(": {constraint}"),
482525
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
483526
));
@@ -490,21 +533,16 @@ pub fn suggest_constraining_type_params<'a>(
490533
.collect::<Vec<_>>();
491534
let suggested = !suggestions.is_empty();
492535
if suggestions.len() == 1 {
493-
let (span, constraint, suggestion, msg) = suggestions.pop().unwrap();
494-
let post = format!(
495-
" with {}trait{} `{constraint}`",
496-
if unstable_suggestion { "unstable " } else { "" },
497-
if constraint.contains('+') { "s" } else { "" },
498-
);
536+
let (span, post, suggestion, msg) = suggestions.pop().unwrap();
499537
let msg = match msg {
500538
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
501-
format!("consider further restricting this bound{post}")
539+
format!("consider further restricting this bound with {post}")
502540
}
503541
SuggestChangingConstraintsMessage::RestrictType { ty } => {
504-
format!("consider restricting type parameter `{ty}`{post}")
542+
format!("consider restricting type parameter `{ty}` with {post}")
505543
}
506544
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
507-
format!("consider further restricting type parameter `{ty}`{post}")
545+
format!("consider further restricting type parameter `{ty}` with {post}")
508546
}
509547
SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
510548
format!("consider removing the `?Sized` bound to make the type parameter `Sized`")

tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied
44
LL | pub struct Structure<C: Tec> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C`
66
|
7-
help: consider further restricting this bound with trait `Bar<5>`
7+
help: consider further restricting this bound with trait `Bar`
88
|
99
LL | pub struct Structure<C: Tec + Bar<5>> {
1010
| ++++++++
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied
1515
LL | _field: C::BarType,
1616
| ^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C`
1717
|
18-
help: consider further restricting this bound with trait `Bar<5>`
18+
help: consider further restricting this bound with trait `Bar`
1919
|
2020
LL | pub struct Structure<C: Tec + Bar<5>> {
2121
| ++++++++

tests/ui/associated-types/defaults-suitability.current.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar`
4747
|
4848
LL | type Bar: Clone = Vec<T>;
4949
| ^^^^^ required by this bound in `Foo::Bar`
50-
help: consider restricting type parameter `T` with trait `std::clone::Clone`
50+
help: consider restricting type parameter `T` with trait `Clone`
5151
|
5252
LL | trait Foo<T: std::clone::Clone> {
5353
| +++++++++++++++++++
@@ -132,7 +132,7 @@ LL | Self::Baz: Clone,
132132
...
133133
LL | type Baz = T;
134134
| --- required by a bound in this associated type
135-
help: consider further restricting type parameter `T` with trait `std::clone::Clone`
135+
help: consider further restricting type parameter `T` with trait `Clone`
136136
|
137137
LL | Self::Baz: Clone, T: std::clone::Clone
138138
| ~~~~~~~~~~~~~~~~~~~~~~

tests/ui/associated-types/defaults-suitability.next.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar`
4747
|
4848
LL | type Bar: Clone = Vec<T>;
4949
| ^^^^^ required by this bound in `Foo::Bar`
50-
help: consider restricting type parameter `T` with trait `std::clone::Clone`
50+
help: consider restricting type parameter `T` with trait `Clone`
5151
|
5252
LL | trait Foo<T: std::clone::Clone> {
5353
| +++++++++++++++++++
@@ -132,7 +132,7 @@ LL | Self::Baz: Clone,
132132
...
133133
LL | type Baz = T;
134134
| --- required by a bound in this associated type
135-
help: consider further restricting type parameter `T` with trait `std::clone::Clone`
135+
help: consider further restricting type parameter `T` with trait `Clone`
136136
|
137137
LL | Self::Baz: Clone, T: std::clone::Clone
138138
| ~~~~~~~~~~~~~~~~~~~~~~

tests/ui/associated-types/hr-associated-type-bound-param-6.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied
44
LL | impl<S, T> X<'_, T> for (S,) {
55
| ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T`
66
|
7-
help: consider restricting type parameter `T` with trait `for<'b> X<'b, T>`
7+
help: consider restricting type parameter `T` with trait `X`
88
|
99
LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
1010
| ++++++++++++++++++

tests/ui/associated-types/issue-27675-unchecked-bounds.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: required by a bound in `copy`
99
|
1010
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
1111
| ^^^^^ required by this bound in `copy`
12-
help: consider restricting type parameter `T` with trait `std::marker::Copy`
12+
help: consider restricting type parameter `T` with trait `Copy`
1313
|
1414
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
1515
| +++++++++++++++++++

tests/ui/associated-types/issue-43784-associated-type.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ note: required by a bound in `Complete::Assoc`
1414
|
1515
LL | type Assoc: Partial<Self>;
1616
| ^^^^^^^^^^^^^ required by this bound in `Complete::Assoc`
17-
help: consider restricting type parameter `T` with trait `std::marker::Copy`
17+
help: consider restricting type parameter `T` with trait `Copy`
1818
|
1919
LL | impl<T: std::marker::Copy> Complete for T {
2020
| +++++++++++++++++++

tests/ui/async-await/issue-70818.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: captured value is not `Send`
99
|
1010
LL | async { (ty, ty1) }
1111
| ^^^ has type `U` which is not `Send`
12-
help: consider restricting type parameter `U` with trait `std::marker::Send`
12+
help: consider restricting type parameter `U` with trait `Send`
1313
|
1414
LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
1515
| +++++++++++++++++++

tests/ui/async-await/issue-86507.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
1414
LL | let x = x;
1515
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
1616
= note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
17-
help: consider further restricting this bound with trait `std::marker::Sync`
17+
help: consider further restricting this bound with trait `Sync`
1818
|
1919
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
2020
| +++++++++++++++++++

tests/ui/binop/issue-93927.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | val == val
66
| |
77
| MyType<T>
88
|
9-
help: consider further restricting this bound with trait `std::cmp::Eq`
9+
help: consider further restricting this bound with trait `Eq`
1010
|
1111
LL | fn cond<T: PartialEq + std::cmp::Eq>(val: MyType<T>) -> bool {
1212
| ++++++++++++++

tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: required by a bound in `Foo`
1010
|
1111
LL | trait Foo : Send+Sync { }
1212
| ^^^^ required by this bound in `Foo`
13-
help: consider further restricting this bound with trait `std::marker::Send`
13+
help: consider further restricting this bound with trait `Send`
1414
|
1515
LL | impl <T: Sync+'static + std::marker::Send> Foo for (T,) { }
1616
| +++++++++++++++++++
@@ -27,7 +27,7 @@ note: required by a bound in `Foo`
2727
|
2828
LL | trait Foo : Send+Sync { }
2929
| ^^^^ required by this bound in `Foo`
30-
help: consider further restricting this bound with trait `std::marker::Sync`
30+
help: consider further restricting this bound with trait `Sync`
3131
|
3232
LL | impl <T: Send + std::marker::Sync> Foo for (T,T) { }
3333
| +++++++++++++++++++

tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ note: required by a bound in `RequiresRequiresShareAndSend`
1414
|
1515
LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
1616
| ^^^^ required by this bound in `RequiresRequiresShareAndSend`
17-
help: consider further restricting this bound with trait `std::marker::Send`
17+
help: consider further restricting this bound with trait `Send`
1818
|
1919
LL | impl <T:Sync+'static + std::marker::Send> RequiresRequiresShareAndSend for X<T> { }
2020
| +++++++++++++++++++

tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: required by a bound in `Foo`
99
|
1010
LL | trait Foo : Send { }
1111
| ^^^^ required by this bound in `Foo`
12-
help: consider further restricting this bound with trait `std::marker::Send`
12+
help: consider further restricting this bound with trait `Send`
1313
|
1414
LL | impl <T: Sync+'static + std::marker::Send> Foo for T { }
1515
| +++++++++++++++++++

tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: required by a bound in `X`
99
|
1010
LL | struct X<F> where F: FnOnce() + 'static + Send {
1111
| ^^^^ required by this bound in `X`
12-
help: consider further restricting this bound with trait `std::marker::Send`
12+
help: consider further restricting this bound with trait `Send`
1313
|
1414
LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send {
1515
| +++++++++++++++++++
@@ -25,7 +25,7 @@ note: required by a bound in `X`
2525
|
2626
LL | struct X<F> where F: FnOnce() + 'static + Send {
2727
| ^^^^ required by this bound in `X`
28-
help: consider further restricting this bound with trait `std::marker::Send`
28+
help: consider further restricting this bound with trait `Send`
2929
|
3030
LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send {
3131
| +++++++++++++++++++

tests/ui/closures/closure-bounds-subtype.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ help: use parentheses to call this type parameter
1515
|
1616
LL | take_const_owned(f());
1717
| ++
18-
help: consider further restricting this bound with trait `std::marker::Sync`
18+
help: consider further restricting this bound with trait `Sync`
1919
|
2020
LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync {
2121
| +++++++++++++++++++

tests/ui/const-generics/issues/issue-61336-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | [x; { N }]
77
= note: the `Copy` trait is required because this value will be copied for each element of the array
88
= help: consider using `core::array::from_fn` to initialize the array
99
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information
10-
help: consider restricting type parameter `T` with trait `std::marker::Copy`
10+
help: consider restricting type parameter `T` with trait `Copy`
1111
|
1212
LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
1313
| +++++++++++++++++++

tests/ui/const-generics/issues/issue-61336.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | [x; N]
77
= note: the `Copy` trait is required because this value will be copied for each element of the array
88
= help: consider using `core::array::from_fn` to initialize the array
99
= help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information
10-
help: consider restricting type parameter `T` with trait `std::marker::Copy`
10+
help: consider restricting type parameter `T` with trait `Copy`
1111
|
1212
LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
1313
| +++++++++++++++++++

tests/ui/consts/ct-var-in-collect_all_mismatches.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LL | fn unsatisfied(self)
1212
LL | where
1313
LL | T: Bar<N>,
1414
| ^^^^^^ required by this bound in `Foo::<T, N>::unsatisfied`
15-
help: consider restricting type parameter `T` with trait `Bar<N>`
15+
help: consider restricting type parameter `T` with trait `Bar`
1616
|
1717
LL | impl<T: Bar<N>, const N: usize> Foo<T, N> {
1818
| ++++++++

tests/ui/dropck/explicit-drop-bounds.bad1.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: required by a bound in `DropMe`
99
|
1010
LL | struct DropMe<T: Copy>(T);
1111
| ^^^^ required by this bound in `DropMe`
12-
help: consider further restricting type parameter `T` with trait `std::marker::Copy`
12+
help: consider further restricting type parameter `T` with trait `Copy`
1313
|
1414
LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
1515
| ~~~~~~~~~~~~~~~~~~~~~~
@@ -25,7 +25,7 @@ note: required by a bound in `DropMe`
2525
|
2626
LL | struct DropMe<T: Copy>(T);
2727
| ^^^^ required by this bound in `DropMe`
28-
help: consider further restricting type parameter `T` with trait `std::marker::Copy`
28+
help: consider further restricting type parameter `T` with trait `Copy`
2929
|
3030
LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy`
3131
| ~~~~~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)