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

non-Clone type, with Clone associated type, as type param leads to confusing behavior in #[derive(Clone)] #124300

Closed
chebbyChefNEQ opened this issue Apr 23, 2024 · 7 comments
Labels
C-bug Category: This is a bug.

Comments

@chebbyChefNEQ
Copy link

chebbyChefNEQ commented Apr 23, 2024

I tried this code:

trait NotClone {
    type AssocClonable: Clone;
}

struct NotCloneImpl;

impl NotClone for NotCloneImpl {
    type AssocClonable = i32;
}

#[derive(Clone)]
struct ShouldBeClone<T: NotClone>
{
    _value: T::AssocClonable
}

fn main() {
    // Compiles with no error or warnings -- minus unused variable
    let a = ShouldBeClone::<NotCloneImpl> { _value: 1 };
    
    // let clone_a: ShouldBeClone<NotCloneImpl> = (&a).clone();
    // let clone_a: ShouldBeClone<NotCloneImpl> = a.clone();
}

the the two clones are uncommented
fails with

   Compiling bugs v0.1.0 (/Users/robmeng/workspace/bugs)
error[E0599]: the method `clone` exists for struct `ShouldBeClone<NotCloneImpl>`, but its trait bounds were not satisfied
  --> main.rs:19:50
   |
5  | struct NotCloneImpl;
   | ------------------- doesn't satisfy `NotCloneImpl: Clone`
...
12 | struct ShouldBeClone<T: NotClone>
   | --------------------------------- method `clone` not found for this struct because it doesn't satisfy `ShouldBeClone<NotCloneImpl>: Clone`
...
19 |     let clone_a: ShouldBeClone<NotCloneImpl> = a.clone();
   |                                                  ^^^^^ method cannot be called on `ShouldBeClone<NotCloneImpl>` due to unsatisfied trait bounds
   |
note: trait bound `NotCloneImpl: Clone` was not satisfied
  --> main.rs:11:10
   |
11 | #[derive(Clone)]
   |          ^^^^^ unsatisfied trait bound introduced in this `derive` macro
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `clone`, perhaps you need to implement it:
           candidate #1: `Clone`
help: consider annotating `NotCloneImpl` with `#[derive(Clone)]`
   |
5  + #[derive(Clone)]
6  | struct NotCloneImpl;
   |

error[E0308]: mismatched types
  --> main.rs:20:48
   |
20 |     let clone_a: ShouldBeClone<NotCloneImpl> = (&a).clone();
   |                  ---------------------------   ^^^^^^^^^^^^ expected `ShouldBeClone<NotCloneImpl>`, found `&ShouldBeClone<NotCloneImpl>`
   |                  |
   |                  expected due to this
   |
   = note: expected struct `ShouldBeClone<_>`
           found reference `&ShouldBeClone<_>`
note: `ShouldBeClone<NotCloneImpl>` does not implement `Clone`, so `&ShouldBeClone<NotCloneImpl>` was cloned instead
  --> main.rs:20:48
   |
20 |     let clone_a: ShouldBeClone<NotCloneImpl> = (&a).clone();
   |                                                ^^^^
   = help: `Clone` is not implemented because the trait bound `NotCloneImpl: Clone` is not satisfied
help: consider annotating `NotCloneImpl` with `#[derive(Clone)]`
   |
5  + #[derive(Clone)]
6  | struct NotCloneImpl;
   |
help: consider annotating `ShouldBeClone<NotCloneImpl>` with `#[derive(Clone)]`
   |
12 + #[derive(Clone)]
13 | struct ShouldBeClone<T: NotClone>
   |

Instead, this happened:
either

  • error that ShouldBeClone::<NotCloneImpl> can not be derive Clone because NotCloneImpl is not Clone
  • handle the case where the struct attribute depends on NotCloneImpl::AssociatedCloneableType

Meta

rustc --version --verbose:

rustc 1.77.2 (25ef9e3d8 2024-04-09)
binary: rustc
commit-hash: 25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04
commit-date: 2024-04-09
host: aarch64-apple-darwin
release: 1.77.2
LLVM version: 17.0.6

@chebbyChefNEQ chebbyChefNEQ added the C-bug Category: This is a bug. label Apr 23, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 23, 2024
@chebbyChefNEQ chebbyChefNEQ changed the title non-Clone type, with Clone associated type, as type param leads to confusing behavior non-Clone type, with Clone associated type, as type param leads to confusing behavior in #[derive(Clone)] Apr 23, 2024
@fmease
Copy link
Member

fmease commented Apr 23, 2024

#[derive] is not “perfect” (precise). The generated impl looks like:

impl<T: Clone/*<-- [!] */ + NotClone>Clone for ShouldBeClone<T>
where
    T::AssocClonable: Clone,
{ /* ... */ }

Meaning it generates a Clone impl that applies to all types T that impl Clone and NotClone etc.

@fmease
Copy link
Member

fmease commented Apr 23, 2024

If want to get rid of the extra Clone bound, you need to replace the #[derive(Clone)] with a manual Clone impl: Playground.

@chebbyChefNEQ
Copy link
Author

#[derive] is not “perfect” (precise). The generated impl looks like:

impl<T: Clone/*<-- [!] */ + NotClone>Clone for ShouldBeClone<T>
where
    T::AssocClonable: Clone,
{ /* ... */ }

Meaning it generates a Clone impl that applies to all types T that impl Clone and NotClone etc.

I see. So this is why it is able to compile and only error when I try to call .clone()

@fmease
Copy link
Member

fmease commented Apr 23, 2024

Closing as duplicate of #26925.

@fmease fmease closed this as not planned Won't fix, can't repro, duplicate, stale Apr 23, 2024
@fmease fmease removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 23, 2024
@fmease
Copy link
Member

fmease commented Apr 23, 2024

I see. So this is why it is able to compile and only error when I try to call .clone()

Exactly!

@fmease
Copy link
Member

fmease commented Apr 23, 2024

Apart from https://crates.io/crates/perfect-derive, there's also https://lib.rs/crates/derivative if you don't want to write the impl manually where you can specify if you want to omit certain bounds with attributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants