Skip to content
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

Disable expl_impl_clone_on_copy when Copy is manually implemented. #1254

Closed
Stebalien opened this issue Oct 2, 2016 · 10 comments · Fixed by #6993
Closed

Disable expl_impl_clone_on_copy when Copy is manually implemented. #1254

Stebalien opened this issue Oct 2, 2016 · 10 comments · Fixed by #6993
Labels
C-bug Category: Clippy is not doing the correct thing I-false-positive Issue: The lint was triggered on code it shouldn't have T-middle Type: Probably requires verifiying types

Comments

@Stebalien
Copy link

Due to some limitations in the deriving infrastructure, it's sometimes necessary to explicitly implement Copy and Clone. In these cases, it would be nice if clippy detected the explicit Copy implementation and didn't warn about the explicit Clone implementation.

@ipetkov
Copy link

ipetkov commented Jun 17, 2017

Just adding a clarification here: for generics, the deriving infrastructure will add bounds for all generic parameters, even when they aren't needed. In those situations a manual implementation is necessary to avoid those bounds, in which situation it would be nice for the warning to be automatically suppressed.

Example:

#![allow(unused)]

use std::marker::PhantomData;

struct Marker<A>(PhantomData<A>);

// Can copy/clone `Marker` regardless of what `A` is
impl<A> Copy for Marker<A> {}
impl<A> Clone for Marker<A> {
    fn clone(&self) -> Self {
        *self
    }
}

struct NoClone;

fn main() {
    let m: Marker<NoClone> = Marker(PhantomData);
    let m2 = m.clone();
}

Following clippy's suggestion here to auto derive either/both of Copy/Clone will prevent the example from compiling.

@mcarton mcarton added C-bug Category: Clippy is not doing the correct thing T-middle Type: Probably requires verifiying types labels Jun 17, 2017
@oli-obk
Copy link
Contributor

oli-obk commented Jun 18, 2017

This seems me like an inconsistent use of PhantomData. The whole point of PhantomData is to treat the field as if it were the inner type, but without taking up space. Shouldn't you be using somehing like PhantomData<* const A> instead? If a type has a !Copy field, then it shouldn't be Copy.

Maybe I'm completely off with my reasoning here... I never fully understood all PhantomData semantics

@mcarton
Copy link
Member

mcarton commented Jun 18, 2017

@oli-obk this example looks ok. PhantomData is mostly used to cheat around lifetimes.You want some type do not outlive some lifetime, but don't actually depend on that lifetime. See for example Iter for slices:

pub struct Iter<'a, T: 'a> {
    ptr: *const T,
    end: *const T,
    _marker: marker::PhantomData<&'a T>,
}

Without the marker, the iterator would not depend on 'a and could outlive the slice!
However the iterator itself is still Copy, whether T is or not. But native derive do not understand that, they see a T, so they want T: Copy.

@oli-obk
Copy link
Contributor

oli-obk commented Jun 18, 2017

That's not true (anymore), otherwise http://play.integer32.com/?gist=f7d889a3a96894cea5f855488f9a94d5&version=stable wouldn't build. There used to be some issues around these derives, but I think most have been solved.

@mcarton
Copy link
Member

mcarton commented Jun 18, 2017

Maybe derives know about reference fields now, but they still don't know about any Foo<T> field (they can't as they operate on AST level).

@oli-obk
Copy link
Contributor

oli-obk commented Jun 18, 2017

They don't need to know anything about Foo<T>, because all they do is generate where Foo<T>: Copy.

#[derive(Copy, Clone)]
struct Foo<'a, T: 'a>(std::marker::PhantomData<&'a T>);

#[derive(Copy, Clone)]
struct Bar<'a, T: 'a>(Foo<'a, T>);

works just fine.

@ipetkov
Copy link

ipetkov commented Jun 18, 2017

@oli-obk I'm using the phantom data to cheat around unused parameters for a builder what will convert Strings into some T. Perhaps storing a PhantomData<*const T> is more correct according to the nomicon, but the derive infrastructure still imposes the same T: Copy/T: Clone bounds I'm trying to avoid.

They don't need to know anything about Foo<T>, because all they do is generate where Foo<T>: Copy.

According to the output of rustdoc the bound is T: Copy and not Foo<T>: Copy for both Foo and Bar (wouldn't impl Copy for Foo<T> where Foo<T>: Copy be impossible to be satisfied?).

As a second data point, this example will fail to compile even though &T is always copy/clone http://play.integer32.com/?gist=d55d20c7c8bfa3f7bffa4d3edeeee844&version=stable

the following trait bounds were not satisfied:
          `NoClone : std::clone::Clone`

@oli-obk
Copy link
Contributor

oli-obk commented Jun 19, 2017

I found rust-lang/rust#26925, so it looks like this issue is going to stay with us.

@dennis-hamester
Copy link

In one of my projects, I have several cases like this:

pub struct Foo(Option<unsafe extern "system" fn()>);

impl Copy for Foo {}

impl Clone for Foo {
    fn clone(&self) -> Self {
        *self
    }
}

Unfortunately, fn pointers with a system ABI are neither Copy nor Clone, which is why I manually implement them.

At the moment, I simply disable expl_impl_clone_on_copy, but it would be great if clippy figured out, that deriving those traits is not an option.

@jplatte
Copy link
Contributor

jplatte commented Oct 5, 2017

As long as this is not fixed, it should be listed as a known problem with the lint. Currently, known problems are "None": https://rust-lang-nursery.github.io/rust-clippy/v0.0.165/index.html#expl_impl_clone_on_copy

@phansch phansch added the I-false-positive Issue: The lint was triggered on code it shouldn't have label Dec 22, 2020
bors added a commit that referenced this issue Mar 28, 2021
Improve `expl_impl_clone_on_copy`

fixes: #1254

changelog: Check to see if the generic constraints are the same as if using derive for `expl_impl_clone_on_copy`
@bors bors closed this as completed in c07103b Mar 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: Clippy is not doing the correct thing I-false-positive Issue: The lint was triggered on code it shouldn't have T-middle Type: Probably requires verifiying types
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants