-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#[derive(Clone, Copy)] doesn't work #108894
Comments
Currently derive macros don't use the best possible bounds, but instead always bound the generic parameters by the given trait. See #26925 for why it's like this. This means your derive macro expands to something like this: #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for TypedAddress<T> {
#[inline]
fn clone(&self) -> TypedAddress<T> {
TypedAddress {
inner: ::core::clone::Clone::clone(&self.inner),
phantom: ::core::clone::Clone::clone(&self.phantom),
}
}
}
#[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for TypedAddress<T> { } Notice the You can solve this by manually implementing impl<T> Clone for TypedAddress<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for TypedAddress<T> {} |
Given that this is true for all built-in derive macros, rustc should out-right state what @SkiFire13 explains above. Doing so might be as hard as implementing "perfect derives", but then again it might not be. |
Copy and Clone are implemented explicitly since deriving these traits doesn't work because of the generics used. See related issue: rust-lang/rust#108894
I have a similar problem with Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e0bd07c4577c18c44e11644201cebaed use core::marker::PhantomData;
#[derive(PartialEq, Eq)]
pub struct Id<T>(PhantomData<T>);
// manual implementation which would break the usage of const patterns
// impl<T> PartialEq for Id<T> { fn eq(&self, _: &Id<T>) -> bool { true } }
// impl<T> Eq for Id<T> {}
// This derive is undesired but cannot be removed without
// breaking the usages below
#[derive(PartialEq, Eq)]
struct SomeNode();
fn accept_eq(_: &impl PartialEq) { }
fn main() {
let node = Id::<SomeNode>(PhantomData);
// this will only work if
// - `Partial/Eq` is implemented manually, or
// - `SomeNode` also needlessly(?) implements `Partial/Eq`
// otherwise: error[E0277]: can't compare `SomeNode` with `SomeNode`
accept_eq(&node);
const CONST_ID: Id::<SomeNode> = Id::<SomeNode>(PhantomData);
// this will work only when `Partial/Eq` is being derived
// otherwise: error: to use a constant of type `Id<SomeNode>` in a pattern,
// `Id<SomeNode>` must be annotated with `#[derive(PartialEq, Eq)]`
match node {
CONST_ID => {}
}
} |
I tried this code:
I expected to see it compiled.
Instead, this happened:
Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: