Skip to content

Commit 2c14bc3

Browse files
authored
Rollup merge of rust-lang#99741 - compiler-errors:copy-impl-impl-generics, r=fee1-dead
Use `impl`'s generics when suggesting fix on bad `impl Copy` See the UI test for a more complicated example, but we weren't correctly suggesting to add bounds given a manual `impl` whose generics didn't match the struct generics. ```rust #[derive(Clone)] struct Wrapper<T>(T); impl<S> Copy for Wrapper<S> {} ``` Coincidentally this fix didn't cause any regressions for `derive(Copy)` impls, I think because those use the same spans in the impl generics as the struct generics, so the machinery still applies the same change.
2 parents 403c1b3 + 1390220 commit 2c14bc3

7 files changed

+103
-18
lines changed

compiler/rustc_typeck/src/coherence/builtin.rs

+8-18
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9494

9595
// We'll try to suggest constraining type parameters to fulfill the requirements of
9696
// their `Copy` implementation.
97-
let mut generics = None;
98-
if let ty::Adt(def, _substs) = self_type.kind() {
99-
let self_def_id = def.did();
100-
if let Some(local) = self_def_id.as_local() {
101-
let self_item = tcx.hir().expect_item(local);
102-
generics = self_item.kind.generics();
103-
}
104-
}
10597
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
10698
let mut bounds = vec![];
10799

@@ -163,16 +155,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
163155
&format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
164156
);
165157
}
166-
if let Some(generics) = generics {
167-
suggest_constraining_type_params(
168-
tcx,
169-
generics,
170-
&mut err,
171-
bounds.iter().map(|(param, constraint, def_id)| {
172-
(param.as_str(), constraint.as_str(), *def_id)
173-
}),
174-
);
175-
}
158+
suggest_constraining_type_params(
159+
tcx,
160+
tcx.hir().get_generics(impl_did).expect("impls always have generics"),
161+
&mut err,
162+
bounds.iter().map(|(param, constraint, def_id)| {
163+
(param.as_str(), constraint.as_str(), *def_id)
164+
}),
165+
);
176166
err.emit();
177167
}
178168
Err(CopyImplementationError::NotAnAdt) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-rustfix
2+
3+
#[derive(Clone)]
4+
struct Wrapper<T>(T);
5+
6+
struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
7+
8+
impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
9+
fn clone(&self) -> Self {
10+
OnlyCopyIfDisplay(std::marker::PhantomData)
11+
}
12+
}
13+
14+
impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
15+
16+
impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
17+
//~^ ERROR the trait `Copy` may not be implemented for this type
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-rustfix
2+
3+
#[derive(Clone)]
4+
struct Wrapper<T>(T);
5+
6+
struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>);
7+
8+
impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> {
9+
fn clone(&self) -> Self {
10+
OnlyCopyIfDisplay(std::marker::PhantomData)
11+
}
12+
}
13+
14+
impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {}
15+
16+
impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
17+
//~^ ERROR the trait `Copy` may not be implemented for this type
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0204]: the trait `Copy` may not be implemented for this type
2+
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9
3+
|
4+
LL | struct Wrapper<T>(T);
5+
| - this field does not implement `Copy`
6+
...
7+
LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
8+
| ^^^^
9+
|
10+
note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
11+
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
12+
|
13+
LL | struct Wrapper<T>(T);
14+
| ^
15+
help: consider restricting type parameter `S`
16+
|
17+
LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
18+
| +++++++++++++++++++
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0204`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
3+
#[derive(Clone)]
4+
struct Wrapper<T>(T);
5+
6+
impl<S: Copy> Copy for Wrapper<S> {}
7+
//~^ ERROR the trait `Copy` may not be implemented for this type
8+
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
3+
#[derive(Clone)]
4+
struct Wrapper<T>(T);
5+
6+
impl<S> Copy for Wrapper<S> {}
7+
//~^ ERROR the trait `Copy` may not be implemented for this type
8+
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0204]: the trait `Copy` may not be implemented for this type
2+
--> $DIR/missing-bound-in-manual-copy-impl.rs:6:9
3+
|
4+
LL | struct Wrapper<T>(T);
5+
| - this field does not implement `Copy`
6+
LL |
7+
LL | impl<S> Copy for Wrapper<S> {}
8+
| ^^^^
9+
|
10+
help: consider restricting type parameter `S`
11+
|
12+
LL | impl<S: Copy> Copy for Wrapper<S> {}
13+
| ++++++
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0204`.

0 commit comments

Comments
 (0)