diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2022-06-02 12:34:55 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2022-06-02 12:54:04 -0700 |
| commit | 8567b686f9b5f85b18341d77814088a4a7409238 (patch) | |
| tree | 42faa2c174734f321a7dc2a5ffdb0de0bc327017 | |
| parent | 395a09c3dafe0c7838c9ca41d2b47bb5e79a5b6d (diff) | |
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.
12 files changed, 211 insertions, 13 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 462fc27009d..9bb64d4023b 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -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, diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index d08d9938708..5953a13506d 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -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) => { diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed index ba1b745ba84..45acf5beb12 100644 --- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -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, diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr index 2353cd079a3..5a84e3b81a6 100644 --- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -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` diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed new file mode 100644 index 00000000000..ac0b14fba83 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed @@ -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() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs new file mode 100644 index 00000000000..31f8cd6fcf7 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs @@ -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() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr new file mode 100644 index 00000000000..03082be690f --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -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`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed new file mode 100644 index 00000000000..304360d48a2 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -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() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs new file mode 100644 index 00000000000..14e1fbb3311 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -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() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr new file mode 100644 index 00000000000..2dc41709fdc --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -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`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs new file mode 100644 index 00000000000..52163bddd4f --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -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() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr new file mode 100644 index 00000000000..1f6932b1fa6 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -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`. |
