Skip to content

#[deriving()], concrete implementations and problems with traits #15923

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

Closed
seb-m opened this issue Jul 23, 2014 · 3 comments
Closed

#[deriving()], concrete implementations and problems with traits #15923

seb-m opened this issue Jul 23, 2014 · 3 comments

Comments

@seb-m
Copy link
Contributor

seb-m commented Jul 23, 2014

The following code fails to compile:

pub trait FooTrait {
    fn new() -> Self;
}

pub struct Foo {
    elem: int
}

impl FooTrait for Foo {
    fn new() -> Foo {
        Foo {
            elem: 42
        }
    }
}

pub struct SFoo<T> {
    elem: int
}

impl<T: FooTrait> SFoo<T> {
    pub fn new() -> SFoo<T> {
        SFoo {
            elem: 42
        }
    }
}

impl<T: FooTrait> Clone for SFoo<T> {
    fn clone(&self) -> SFoo<T> {
        SFoo {
            elem: self.elem
        }
    }
}

#[deriving(Clone)]
struct Bar<T> {
    elem: SFoo<T>
}

impl<T: FooTrait> Bar<T> {
    fn new() -> Bar<T> {
        Bar {
            elem: SFoo::new()
        }
    }
}

fn main() {
    let bar: Bar<Foo> = Bar::new();
}

With the following error:

r.rs:41:5: 41:18 error: failed to find an implementation of trait FooTrait for T
r.rs:41     elem: SFoo<T>
            ^~~~~~~~~~~~~
note: in expansion of #[deriving]

Whereas when #[deriving(Clone)] is used on SFoo instead of providing a concrete implementation for the Clone trait it compiles correctly:

pub trait FooTrait {
    fn new() -> Self;
}

pub struct Foo {
    elem: int
}

impl FooTrait for Foo {
    fn new() -> Foo {
        Foo {
            elem: 42
        }
    }
}

#[deriving(Clone)]
pub struct SFoo<T> {
    elem: int
}

impl<T: FooTrait> SFoo<T> {
    pub fn new() -> SFoo<T> {
        SFoo {
            elem: 42
        }
    }
}

#[deriving(Clone)]
struct Bar<T> {
    elem: SFoo<T>
}

impl<T: FooTrait> Bar<T> {
    fn new() -> Bar<T> {
        Bar {
            elem: SFoo::new()
        }
    }
}

fn main() {
    let bar: Bar<Foo> = Bar::new();
}

It seems to me that the code in the first case should also compile without error.

@alexcrichton
Copy link
Member

Closing as working as intended, the deriving(Clone) code will automatically add T: Clone for all type parameters on a struct. In the first piece of code you require T to adhere to FooTrait to implement Clone, but in the second piece you only require Clone (from deriving(Clone)).

You'll likely want to either derive clone in both circumstances or manually implement Clone in both.

@seb-m
Copy link
Contributor Author

seb-m commented Jul 23, 2014

Ok, thanks for the explanation, that's too bad though :(

Of course I'd prefer using deriving(Clone) as much as possible but because on one struct I can't rely on the code generated by deriving(Clone) I now must also implement Clone in a lot more places.

@alexcrichton
Copy link
Member

We've been discussing recently how one might customize deriving, but nothing concrete is currently implemented as of yet.

bors added a commit to rust-lang-ci/rust that referenced this issue Feb 18, 2024
…r=Veykril

feat: ignored and disabled macro expansion

Supersedes rust-lang#15117, I was having some conflicts after a rebase and since I didn't remember much of it I started clean instead.

The end result is pretty much the same as the linked PR, but instead of proc macro lookups, I marked the expanders that explicitly cannot be expanded and we shouldn't even attempt to do so.

## Unresolved questions

- [ ] I introduced a `DISABLED_ID` next to `DUMMY_ID` in `hir-expand`'s `ProcMacroExpander`, that is effectively exactly the same thing with slightly different semantics, dummy macros are not (yet) expanded probably due to errors, while not expanding disabled macros is part of the usual flow. I'm not sure if it's the right way to handle this, I also thought of just adding a flag instead of replacing the macro ID, so that the disabled macro can still be expanded for any reason if needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@alexcrichton @seb-m and others