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.
This commit is contained in:
Esteban Küber 2022-06-02 12:34:55 -07:00
parent 395a09c3da
commit 8567b686f9
12 changed files with 211 additions and 13 deletions

View File

@ -272,7 +272,10 @@ pub fn suggest_constraining_type_params<'a>(
continue;
}
let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
constraint.sort();
constraint.dedup();
let constraint = constraint.join(" + ");
let mut suggest_restrict = |span, bound_list_non_empty| {
suggestions.push((
span,

View File

@ -11,8 +11,7 @@ use rustc_infer::infer;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable};
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
use rustc_trait_selection::traits::predicate_for_trait_def;
@ -91,6 +90,19 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
E0204,
"the trait `Copy` may not be implemented for this type"
);
// We'll try to suggest constraining type parameters to fulfill the requirements of
// their `Copy` implementation.
let mut generics = None;
if let ty::Adt(def, _substs) = self_type.kind() {
let self_def_id = def.did();
if let Some(local) = self_def_id.as_local() {
let self_item = tcx.hir().expect_item(local);
generics = self_item.kind.generics();
}
}
let mut bounds = vec![];
for (field, ty) in fields {
let field_span = tcx.def_span(field.did);
err.span_label(field_span, "this field does not implement `Copy`");
@ -123,9 +135,34 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
),
);
}
if let ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::ImplPolarity::Positive,
..
}) = error_predicate.kind().skip_binder()
{
let ty = trait_ref.self_ty();
if let ty::Param(_) = ty.kind() {
bounds.push((
format!("{ty}"),
trait_ref.print_only_trait_path().to_string(),
Some(trait_ref.def_id),
));
}
}
}
});
}
if let Some(generics) = generics {
suggest_constraining_type_params(
tcx,
generics,
&mut err,
bounds.iter().map(|(param, constraint, def_id)| {
(param.as_str(), constraint.as_str(), *def_id)
}),
);
}
err.emit();
}
Err(CopyImplementationError::NotAnAdt) => {

View File

@ -21,7 +21,7 @@ fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
(t, t) //~ use of moved value: `t`
}
fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
//~^ HELP consider restricting type parameter `T`
(t, t) //~ use of moved value: `t`
}
@ -39,14 +39,14 @@ trait A {}
trait B {}
// Test where bounds are added with different bound placements
fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
//~^ HELP consider restricting type parameter `T`
(t, t) //~ use of moved value: `t`
}
fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
where
T: A + Trait + Copy,
T: A + Copy + Trait,
//~^ HELP consider further restricting this bound
{
(t, t) //~ use of moved value: `t`
@ -54,14 +54,14 @@ where
fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
where
T: A + Trait + Copy,
T: A + Copy + Trait,
//~^ HELP consider further restricting this bound
T: B,
{
(t, t) //~ use of moved value: `t`
}
fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
//~^ HELP consider further restricting this bound
where
T: B,

View File

@ -75,7 +75,7 @@ LL | (t, t)
|
help: consider restricting type parameter `T`
|
LL | fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
| ++++++++++++++
error[E0382]: use of moved value: `t`
@ -91,7 +91,7 @@ LL | (t, t)
|
help: consider restricting type parameter `T`
|
LL | fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
| ++++++++++++++
error[E0382]: use of moved value: `t`
@ -107,7 +107,7 @@ LL | (t, t)
|
help: consider further restricting this bound
|
LL | T: A + Trait + Copy,
LL | T: A + Copy + Trait,
| ++++++++++++++
error[E0382]: use of moved value: `t`
@ -123,7 +123,7 @@ LL | (t, t)
|
help: consider further restricting this bound
|
LL | T: A + Trait + Copy,
LL | T: A + Copy + Trait,
| ++++++++++++++
error[E0382]: use of moved value: `t`
@ -139,7 +139,7 @@ LL | (t, t)
|
help: consider further restricting this bound
|
LL | fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
| ++++++++++++++
error[E0382]: use of moved value: `t`

View File

@ -0,0 +1,16 @@
// run-rustfix
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Debug + Copy + Clone>{
pub x: T,
pub y: T
}
#[derive(Debug, Copy, Clone)]
pub struct AABB<K: Debug + std::marker::Copy>{
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
pub size: Vector2<K>
}
fn main() {}

View File

@ -0,0 +1,16 @@
// run-rustfix
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Debug + Copy + Clone>{
pub x: T,
pub y: T
}
#[derive(Debug, Copy, Clone)]
pub struct AABB<K: Debug>{
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
pub size: Vector2<K>
}
fn main() {}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `K: Copy` is not satisfied
--> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14
|
LL | pub loc: Vector2<K>,
| ^^^^^^^^^^ the trait `Copy` is not implemented for `K`
|
note: required by a bound in `Vector2`
--> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31
|
LL | pub struct Vector2<T: Debug + Copy + Clone>{
| ^^^^ required by this bound in `Vector2`
help: consider further restricting this bound
|
LL | pub struct AABB<K: Debug + std::marker::Copy>{
| +++++++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,16 @@
//run-rustfix
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Debug + Copy + Clone>{
pub x: T,
pub y: T
}
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
pub struct AABB<K: Copy + Debug>{
pub loc: Vector2<K>,
pub size: Vector2<K>
}
fn main() {}

View File

@ -0,0 +1,16 @@
//run-rustfix
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Debug + Copy + Clone>{
pub x: T,
pub y: T
}
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
pub struct AABB<K: Copy>{
pub loc: Vector2<K>,
pub size: Vector2<K>
}
fn main() {}

View File

@ -0,0 +1,30 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17
|
LL | #[derive(Debug, Copy, Clone)]
| ^^^^
LL | pub struct AABB<K: Copy>{
LL | pub loc: Vector2<K>,
| ------------------- this field does not implement `Copy`
LL | pub size: Vector2<K>
| -------------------- this field does not implement `Copy`
|
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:5
|
LL | pub loc: Vector2<K>,
| ^^^^^^^^^^^^^^^^^^^
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
--> $DIR/missing-bound-in-derive-copy-impl-3.rs:13:5
|
LL | 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 further restricting this bound
|
LL | pub struct AABB<K: Copy + Debug>{
| +++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0204`.

View File

@ -0,0 +1,15 @@
use std::fmt::Debug;
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Debug + Copy + Clone>{
pub x: T,
pub y: T
}
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
pub struct AABB<K>{
pub loc: Vector2<K>,
pub size: Vector2<K>
}
fn main() {}

View File

@ -0,0 +1,30 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-derive-copy-impl.rs:9:17
|
LL | #[derive(Debug, Copy, Clone)]
| ^^^^
LL | pub struct AABB<K>{
LL | pub loc: Vector2<K>,
| ------------------- this field does not implement `Copy`
LL | pub size: Vector2<K>
| -------------------- this field does not implement `Copy`
|
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
--> $DIR/missing-bound-in-derive-copy-impl.rs:11:5
|
LL | pub loc: Vector2<K>,
| ^^^^^^^^^^^^^^^^^^^
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
--> $DIR/missing-bound-in-derive-copy-impl.rs:12:5
|
LL | 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`
|
LL | pub struct AABB<K: Debug>{
| +++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0204`.