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

Failing to use derive for nested types parameterized on associated types #31518

Closed
asajeffrey opened this issue Feb 9, 2016 · 13 comments
Closed

Comments

@asajeffrey
Copy link

In this example (https://play.rust-lang.org/?gist=5dde58647c1e97b97f46) there's an error failing to derive Debug for Bang:

pub trait Foo { type Bar; }

#[derive(Debug)]
pub enum Baz<F> where F: Foo { Baz(F::Bar) }

#[derive(Debug)]
pub enum Bang<F> where F: Foo { Bang(Baz<F>) }

The error is error: the traitcore::fmt::Debugis not implemented for the type::Bar[E0277]. It works for Baz, you only get problems when you nest types parameterized on associated types.

@asajeffrey
Copy link
Author

Discussed on irc with @durka.

@durka
Copy link
Contributor

durka commented Feb 9, 2016

If the expansion code for #[derive(Debug)] were smart enough to add where Baz<F>: Debug to the impl, then it would work. I'm not sure if this is too much magic or not, but I plan to take a look.

@durka
Copy link
Contributor

durka commented Feb 9, 2016

Here's a playpen with the pretty-expanded form of the original code, with the bound on line 26 added to make it compile.

@jonas-schievink
Copy link
Contributor

jonas-schievink commented Feb 9, 2016

Duplicate of #26925

Edit: Or rather, would be fixed by fixing #26925 properly

@durka
Copy link
Contributor

durka commented Feb 9, 2016

Hmm yep and it's basically unfixable as per the discussion there, at least with structs which can have private members, because adding where Baz<F>: Debug could hit "private type in public type signature". Hackish ways I can think of to get around that are exempting derived impls from that error, or allowing users to specify additional necessary bounds (ick): #[derive(Debug(Baz<F>))].

@asajeffrey
Copy link
Author

Yes, for the case:

pub trait Foo { type Bar; }

#[derive(Debug)]
enum Baz<F> where F: Foo { Baz(F::Bar) }

#[derive(Debug)]
pub enum Bang<F> where F: Foo { Bang(Baz<F>) }

you'd need the derivation for Bang<F>: Debug to recursively get the bounds for Baz<F>: Debug, which are F: Foo+Debug. This sounds tricky.

@durka
Copy link
Contributor

durka commented Feb 9, 2016

It's worse than tricky. If you turn them into structs

pub trait Foo { type Bar; }

#[derive(Debug)]
struct Baz<F> where F: Foo { baz: F::Bar }

#[derive(Debug)]
pub struct Bang<F> where F: Foo { bang: Baz<F> }

then you aren't even allowed to write the necessary bound.

@asajeffrey
Copy link
Author

Isn't the bound F: Debug+Foo?

@durka
Copy link
Contributor

durka commented Feb 9, 2016

Actually the most specific bound is F: Foo, <F as Foo>::Bar: Debug but that's not discoverable from the point of view of #[derive]. An equivalent bound is F: Foo, Baz<F>: Debug but you can't write that due to the privacy error.

@asajeffrey
Copy link
Author

You could recursively derive the bounds for Baz<F>: Debug, which are F: Foo+Debug.

@durka
Copy link
Contributor

durka commented Feb 9, 2016

Yeah, I could, but #[derive] can't, unless we add some magic syntax as suggested in the other issue, or if the privacy checker tried that before triggering an error.

@asajeffrey
Copy link
Author

Yes, it sounds like #[derive] is missing enough type information to be able to do the recursive call.

@Mark-Simulacrum
Copy link
Member

Closing in favor of #32872.

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

4 participants