Skip to content

Commit b71ddd6

Browse files
authored
Rollup merge of #97664 - estebank:suggest-bound-derive-copy, r=compiler-errors
On E0204 suggest missing type param bounds ``` error[E0204]: the trait `Copy` may not be implemented for this type --> f42.rs:9:17 | 9 | #[derive(Debug, Copy, Clone)] | ^^^^ 10 | pub struct AABB<K>{ 11 | pub loc: Vector2<K>, | ------------------- this field does not implement `Copy` 12 | pub size: Vector2<K> | -------------------- this field does not implement `Copy` | note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` --> f42.rs:11:5 | 11 | pub loc: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` --> f42.rs:12:5 | 12 | pub size: Vector2<K> | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` | 10 | pub struct AABB<K: Debug>{ | +++++++ ``` Fix #89137.
2 parents a6d7939 + f9aa2e0 commit b71ddd6

12 files changed

+219
-21
lines changed

compiler/rustc_middle/src/ty/diagnostics.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ pub fn suggest_constraining_type_params<'a>(
272272
continue;
273273
}
274274

275-
let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
275+
let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
276+
constraint.sort();
277+
constraint.dedup();
278+
let constraint = constraint.join(" + ");
276279
let mut suggest_restrict = |span, bound_list_non_empty| {
277280
suggestions.push((
278281
span,

compiler/rustc_typeck/src/coherence/builtin.rs

+53-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! up data structures required by type-checking/codegen.
33
44
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
5-
use rustc_errors::struct_span_err;
5+
use rustc_errors::{struct_span_err, MultiSpan};
66
use rustc_hir as hir;
77
use rustc_hir::def_id::{DefId, LocalDefId};
88
use rustc_hir::lang_items::LangItem;
@@ -11,12 +11,12 @@ use rustc_infer::infer;
1111
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1212
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
1313
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
14-
use rustc_middle::ty::TypeFoldable;
15-
use rustc_middle::ty::{self, Ty, TyCtxt};
14+
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable};
1615
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
1716
use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
1817
use rustc_trait_selection::traits::predicate_for_trait_def;
1918
use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
19+
use std::collections::BTreeMap;
2020

2121
pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
2222
let lang_items = tcx.lang_items();
@@ -91,6 +91,20 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9191
E0204,
9292
"the trait `Copy` may not be implemented for this type"
9393
);
94+
95+
// We'll try to suggest constraining type parameters to fulfill the requirements of
96+
// their `Copy` implementation.
97+
let mut generics = None;
98+
if let ty::Adt(def, _substs) = self_type.kind() {
99+
let self_def_id = def.did();
100+
if let Some(local) = self_def_id.as_local() {
101+
let self_item = tcx.hir().expect_item(local);
102+
generics = self_item.kind.generics();
103+
}
104+
}
105+
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
106+
let mut bounds = vec![];
107+
94108
for (field, ty) in fields {
95109
let field_span = tcx.def_span(field.did);
96110
err.span_label(field_span, "this field does not implement `Copy`");
@@ -115,17 +129,46 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
115129
// FIXME: This error could be more descriptive, especially if the error_predicate
116130
// contains a foreign type or if it's a deeply nested type...
117131
if error_predicate != error.root_obligation.predicate {
118-
err.span_note(
119-
error.obligation.cause.span,
120-
&format!(
121-
"the `Copy` impl for `{}` requires that `{}`",
122-
ty, error_predicate
123-
),
124-
);
132+
errors
133+
.entry((ty.to_string(), error_predicate.to_string()))
134+
.or_default()
135+
.push(error.obligation.cause.span);
136+
}
137+
if let ty::PredicateKind::Trait(ty::TraitPredicate {
138+
trait_ref,
139+
polarity: ty::ImplPolarity::Positive,
140+
..
141+
}) = error_predicate.kind().skip_binder()
142+
{
143+
let ty = trait_ref.self_ty();
144+
if let ty::Param(_) = ty.kind() {
145+
bounds.push((
146+
format!("{ty}"),
147+
trait_ref.print_only_trait_path().to_string(),
148+
Some(trait_ref.def_id),
149+
));
150+
}
125151
}
126152
}
127153
});
128154
}
155+
for ((ty, error_predicate), spans) in errors {
156+
let span: MultiSpan = spans.into();
157+
err.span_note(
158+
span,
159+
&format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
160+
);
161+
}
162+
if let Some(generics) = generics {
163+
suggest_constraining_type_params(
164+
tcx,
165+
generics,
166+
&mut err,
167+
bounds.iter().map(|(param, constraint, def_id)| {
168+
(param.as_str(), constraint.as_str(), *def_id)
169+
}),
170+
);
171+
}
129172
err.emit();
130173
}
131174
Err(CopyImplementationError::NotAnAdt) => {

src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
2121
(t, t) //~ use of moved value: `t`
2222
}
2323

24-
fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
24+
fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
2525
//~^ HELP consider restricting type parameter `T`
2626
(t, t) //~ use of moved value: `t`
2727
}
@@ -39,29 +39,29 @@ trait A {}
3939
trait B {}
4040

4141
// Test where bounds are added with different bound placements
42-
fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
42+
fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
4343
//~^ HELP consider restricting type parameter `T`
4444
(t, t) //~ use of moved value: `t`
4545
}
4646

4747
fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
4848
where
49-
T: A + Trait + Copy,
49+
T: A + Copy + Trait,
5050
//~^ HELP consider further restricting this bound
5151
{
5252
(t, t) //~ use of moved value: `t`
5353
}
5454

5555
fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
5656
where
57-
T: A + Trait + Copy,
57+
T: A + Copy + Trait,
5858
//~^ HELP consider further restricting this bound
5959
T: B,
6060
{
6161
(t, t) //~ use of moved value: `t`
6262
}
6363

64-
fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
64+
fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
6565
//~^ HELP consider further restricting this bound
6666
where
6767
T: B,

src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ LL | (t, t)
7575
|
7676
help: consider restricting type parameter `T`
7777
|
78-
LL | fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
78+
LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
7979
| ++++++++++++++
8080

8181
error[E0382]: use of moved value: `t`
@@ -91,7 +91,7 @@ LL | (t, t)
9191
|
9292
help: consider restricting type parameter `T`
9393
|
94-
LL | fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
94+
LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
9595
| ++++++++++++++
9696

9797
error[E0382]: use of moved value: `t`
@@ -107,7 +107,7 @@ LL | (t, t)
107107
|
108108
help: consider further restricting this bound
109109
|
110-
LL | T: A + Trait + Copy,
110+
LL | T: A + Copy + Trait,
111111
| ++++++++++++++
112112

113113
error[E0382]: use of moved value: `t`
@@ -123,7 +123,7 @@ LL | (t, t)
123123
|
124124
help: consider further restricting this bound
125125
|
126-
LL | T: A + Trait + Copy,
126+
LL | T: A + Copy + Trait,
127127
| ++++++++++++++
128128

129129
error[E0382]: use of moved value: `t`
@@ -139,7 +139,7 @@ LL | (t, t)
139139
|
140140
help: consider further restricting this bound
141141
|
142-
LL | fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
142+
LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
143143
| ++++++++++++++
144144

145145
error[E0382]: use of moved value: `t`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
use std::fmt::Debug;
3+
4+
#[derive(Debug, Copy, Clone)]
5+
pub struct Vector2<T: Debug + Copy + Clone>{
6+
pub x: T,
7+
pub y: T
8+
}
9+
10+
#[derive(Debug, Copy, Clone)]
11+
pub struct AABB<K: Debug + std::marker::Copy>{
12+
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
13+
pub size: Vector2<K>
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
use std::fmt::Debug;
3+
4+
#[derive(Debug, Copy, Clone)]
5+
pub struct Vector2<T: Debug + Copy + Clone>{
6+
pub x: T,
7+
pub y: T
8+
}
9+
10+
#[derive(Debug, Copy, Clone)]
11+
pub struct AABB<K: Debug>{
12+
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
13+
pub size: Vector2<K>
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0277]: the trait bound `K: Copy` is not satisfied
2+
--> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14
3+
|
4+
LL | pub loc: Vector2<K>,
5+
| ^^^^^^^^^^ the trait `Copy` is not implemented for `K`
6+
|
7+
note: required by a bound in `Vector2`
8+
--> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31
9+
|
10+
LL | pub struct Vector2<T: Debug + Copy + Clone>{
11+
| ^^^^ required by this bound in `Vector2`
12+
help: consider further restricting this bound
13+
|
14+
LL | pub struct AABB<K: Debug + std::marker::Copy>{
15+
| +++++++++++++++++++
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//run-rustfix
2+
use std::fmt::Debug;
3+
4+
#[derive(Debug, Copy, Clone)]
5+
pub struct Vector2<T: Debug + Copy + Clone>{
6+
pub x: T,
7+
pub y: T
8+
}
9+
10+
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
11+
pub struct AABB<K: Copy + Debug>{
12+
pub loc: Vector2<K>,
13+
pub size: Vector2<K>
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//run-rustfix
2+
use std::fmt::Debug;
3+
4+
#[derive(Debug, Copy, Clone)]
5+
pub struct Vector2<T: Debug + Copy + Clone>{
6+
pub x: T,
7+
pub y: T
8+
}
9+
10+
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
11+
pub struct AABB<K: Copy>{
12+
pub loc: Vector2<K>,
13+
pub size: Vector2<K>
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0204]: the trait `Copy` may not be implemented for this type
2+
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17
3+
|
4+
LL | #[derive(Debug, Copy, Clone)]
5+
| ^^^^
6+
LL | pub struct AABB<K: Copy>{
7+
LL | pub loc: Vector2<K>,
8+
| ------------------- this field does not implement `Copy`
9+
LL | pub size: Vector2<K>
10+
| -------------------- this field does not implement `Copy`
11+
|
12+
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
13+
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:5
14+
|
15+
LL | pub loc: Vector2<K>,
16+
| ^^^^^^^^^^^^^^^^^^^
17+
LL | pub size: Vector2<K>
18+
| ^^^^^^^^^^^^^^^^^^^^
19+
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
help: consider further restricting this bound
21+
|
22+
LL | pub struct AABB<K: Copy + Debug>{
23+
| +++++++
24+
25+
error: aborting due to previous error
26+
27+
For more information about this error, try `rustc --explain E0204`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use std::fmt::Debug;
2+
3+
#[derive(Debug, Copy, Clone)]
4+
pub struct Vector2<T: Debug + Copy + Clone>{
5+
pub x: T,
6+
pub y: T
7+
}
8+
9+
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
10+
pub struct AABB<K>{
11+
pub loc: Vector2<K>,
12+
pub size: Vector2<K>
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0204]: the trait `Copy` may not be implemented for this type
2+
--> $DIR/missing-bound-in-derive-copy-impl.rs:9:17
3+
|
4+
LL | #[derive(Debug, Copy, Clone)]
5+
| ^^^^
6+
LL | pub struct AABB<K>{
7+
LL | pub loc: Vector2<K>,
8+
| ------------------- this field does not implement `Copy`
9+
LL | pub size: Vector2<K>
10+
| -------------------- this field does not implement `Copy`
11+
|
12+
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
13+
--> $DIR/missing-bound-in-derive-copy-impl.rs:11:5
14+
|
15+
LL | pub loc: Vector2<K>,
16+
| ^^^^^^^^^^^^^^^^^^^
17+
LL | pub size: Vector2<K>
18+
| ^^^^^^^^^^^^^^^^^^^^
19+
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
help: consider restricting type parameter `K`
21+
|
22+
LL | pub struct AABB<K: Debug>{
23+
| +++++++
24+
25+
error: aborting due to previous error
26+
27+
For more information about this error, try `rustc --explain E0204`.

0 commit comments

Comments
 (0)