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.
This commit is contained in:
Dylan DPC 2022-06-03 11:18:26 +02:00 committed by GitHub
commit b71ddd6861
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 219 additions and 21 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

@ -2,7 +2,7 @@
//! up data structures required by type-checking/codegen.
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
@ -11,12 +11,12 @@ 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;
use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
use std::collections::BTreeMap;
pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
let lang_items = tcx.lang_items();
@ -91,6 +91,20 @@ 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 errors: BTreeMap<_, Vec<_>> = Default::default();
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`");
@ -115,17 +129,46 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
// FIXME: This error could be more descriptive, especially if the error_predicate
// contains a foreign type or if it's a deeply nested type...
if error_predicate != error.root_obligation.predicate {
err.span_note(
error.obligation.cause.span,
&format!(
"the `Copy` impl for `{}` requires that `{}`",
ty, error_predicate
),
);
errors
.entry((ty.to_string(), error_predicate.to_string()))
.or_default()
.push(error.obligation.cause.span);
}
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),
));
}
}
}
});
}
for ((ty, error_predicate), spans) in errors {
let span: MultiSpan = spans.into();
err.span_note(
span,
&format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
);
}
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,27 @@
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>,
| ^^^^^^^^^^^^^^^^^^^
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,27 @@
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>,
| ^^^^^^^^^^^^^^^^^^^
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`.