Skip to content

Strange auto derive behaviour with associated types #33711

Closed
@CasualX

Description

@CasualX

Auto deriving impls for a generic struct which only contains instances of associated types (not the generics themselves) unnecessarily constrains the impl for the struct.

I tried this code: https://is.gd/V6mqWI

pub trait Trait: Clone {
    type Type: Copy + Clone;
}

#[derive(Copy, Clone)]
pub struct ImplT;
impl Trait for ImplT {
    type Type = i32;
}

// Here is the problem, auto derive for `Copy` does nothing.
// What I believe is happening is that impl for `Copy` is unnecessarily constraining `T` itself must be `Copy`.
#[derive(Copy, Clone)]
pub struct NewT<T: Trait>(pub T::Type);
// Workaround:
//impl<T: Trait> Copy for NewT<T> where T::Type: Copy {}

#[derive(Clone)]
pub struct Foo<T: Trait>(T::Type);
impl<T: Trait> Foo<T> {
    pub fn get_if<F>(&self, f: F) -> Option<NewT<T>>
        where F: FnOnce(NewT<T>) -> bool {
        let newt = NewT(self.0);
        if f(newt) {
            Some(newt)
        }
        else {
            None
        }
    }
}

fn main() {
    let foo = Foo::<ImplT>(42);
    foo.get_if(|newt| true);
}

I expected to see this happen: NewT<T> is copyable.

Instead this happened:

<anon>:25:18: 25:22 error: use of moved value: `newt` [E0382]
<anon>:25             Some(newt)
                           ^~~~
<anon>:25:18: 25:22 help: see the detailed explanation for E0382
<anon>:24:14: 24:18 note: `newt` moved here because it has type `NewT<T>`, which is non-copyable
<anon>:24         if f(newt) {
                       ^~~~
error: aborting due to previous error
playpen: application terminated with error code 101

Workaround: Instead of auto deriving Copy for NewT<T>, manually implement it like so:

#[derive(Clone)]
pub struct NewT<T: Trait>(pub T::Type);
impl<T: Trait> Copy for NewT<T> where T::Type: Copy {}

Meta

I used playpen; Debug, Stable, but the same error happens with every option I select.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions