Skip to content

Commit

Permalink
Rollup merge of rust-lang#97664 - estebank:suggest-bound-derive-copy,…
Browse files Browse the repository at this point in the history
… 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 rust-lang#89137.
  • Loading branch information
Dylan-DPC authored Jun 3, 2022
2 parents a6d7939 + f9aa2e0 commit b71ddd6
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 21 deletions.
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
63 changes: 53 additions & 10 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -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`");
Expand All @@ -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) => {
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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`
}
Expand All @@ -39,29 +39,29 @@ 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`
}

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,
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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`
Expand All @@ -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`
Expand All @@ -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`
Expand All @@ -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`
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs
Original file line number Diff line number Diff line change
@@ -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() {}
19 changes: 19 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs
Original file line number Diff line number Diff line change
@@ -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() {}
27 changes: 27 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
Original file line number Diff line number Diff line change
@@ -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`.
15 changes: 15 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs
Original file line number Diff line number Diff line change
@@ -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() {}
27 changes: 27 additions & 0 deletions src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit b71ddd6

Please sign in to comment.