Use impl generics when suggesting fix on copy impl

This commit is contained in:
Michael Goulet 2022-07-26 01:37:06 +00:00
parent 6dbae3ad19
commit 1390220ff2
7 changed files with 103 additions and 18 deletions

View File

@ -94,14 +94,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
// 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![];
@ -163,16 +155,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
&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)
}),
);
}
suggest_constraining_type_params(
tcx,
tcx.hir().get_generics(impl_did).expect("impls always have 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

@ -0,0 +1,19 @@
// run-rustfix
#[derive(Clone)]
struct Wrapper<T>(T);
struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
fn clone(&self) -> Self {
OnlyCopyIfDisplay(std::marker::PhantomData)
}
}
impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
//~^ ERROR the trait `Copy` may not be implemented for this type
fn main() {}

View File

@ -0,0 +1,19 @@
// run-rustfix
#[derive(Clone)]
struct Wrapper<T>(T);
struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
fn clone(&self) -> Self {
OnlyCopyIfDisplay(std::marker::PhantomData)
}
}
impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
//~^ ERROR the trait `Copy` may not be implemented for this type
fn main() {}

View File

@ -0,0 +1,22 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
...
LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
| ^^^^
|
note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
|
LL | struct Wrapper<T>(T);
| ^
help: consider restricting type parameter `S`
|
LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
| +++++++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0204`.

View File

@ -0,0 +1,9 @@
// run-rustfix
#[derive(Clone)]
struct Wrapper<T>(T);
impl<S: Copy> Copy for Wrapper<S> {}
//~^ ERROR the trait `Copy` may not be implemented for this type
fn main() {}

View File

@ -0,0 +1,9 @@
// run-rustfix
#[derive(Clone)]
struct Wrapper<T>(T);
impl<S> Copy for Wrapper<S> {}
//~^ ERROR the trait `Copy` may not be implemented for this type
fn main() {}

View File

@ -0,0 +1,17 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/missing-bound-in-manual-copy-impl.rs:6:9
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
LL |
LL | impl<S> Copy for Wrapper<S> {}
| ^^^^
|
help: consider restricting type parameter `S`
|
LL | impl<S: Copy> Copy for Wrapper<S> {}
| ++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0204`.