-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
enable macro visits in deriving #33769
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
There's a subtle issue here. The reason derivings walk the member types is to find mentions of associated types, to add bounds. If a type macro generates this mention, then with this patch the deriving code will miss it: macro_rules! useassoc {
($t:ident, $assoc:ident) => { ($t, $t::$assoc) }
}
trait HasAssoc { type Type; }
#[derive(Debug)]
struct Thing1<T: HasAssoc> {
thing: useassoc!(T, Type)
}
#[derive(Debug)]
struct Thing2<T: HasAssoc> {
thing: (T, T::Type)
} generates impl <T: ::std::fmt::Debug + HasAssoc> ::std::fmt::Debug for Thing1<T> {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Thing1 { thing: ref __self_0_0 } => {
let mut builder = __arg_0.debug_struct("Thing1");
let _ = builder.field("thing", &&(*__self_0_0));
builder.finish()
}
}
}
}
impl <T: ::std::fmt::Debug + HasAssoc> ::std::fmt::Debug for Thing2<T> where
T::Type: ::std::fmt::Debug {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Thing2 { thing: ref __self_0_0 } => {
let mut builder = __arg_0.debug_struct("Thing2");
let _ = builder.field("thing", &&(*__self_0_0));
builder.finish()
}
}
}
} and there we've got a Debug impl that will fail typeck 😿 Fully fixing this seems like it would require moving derivings to after macro expansion, which sounds unlikely. A possible hack is to just copy the macro and generate |
Pushed a new test which will fail Travis, to show the problem. |
r? @nrc |
Overriding |
Expanding derive happens at the same time as macro expansion. I expect that the right fix for this is that if derive encounters a macro in type position, then to eagerly expand it. That should be possible, because the input to derive must parse (we have the AST, not just tokens). Changing the ordering of expansion in this case should be OK, because we know exactly what derive is doing, and this should just be a change to the derive code, not a change to the expander. However, I can imagine this might be easier said than done, in which case filing an issue for the non-type checking expansion and leaving a FIXME in the code seem fine to me. |
@nrc any pointers for functions I can call to expand the macro? Failing that, am I reading you correctly to say that having |
Per discussion on IRC, there are four options:
My preference is for 3 if possible, then 2a, and then 1. Other opinions? |
@durka want to reopen and land this? |
Sure. I'm out of town until Monday though.
|
@durka ok, I might cherry-pick a commit off this branch then. |
Treat `MultiDecorator`s as a special case of `MultiModifier`s This deals with rust-lang#32950 by using @durka's [option 1](rust-lang#33769 (comment)). r? @nrc
@durka @nikomatsakis Just opened rust-lang/rfcs#1671 which covers the deriving privacy interactions. |
Fixes #32950.
There's a warning in src/libsyntax/visit.rs saying not to do this, but it seems to fix the ICE and the other deriving tests survive. The "note about macros above" seems to be this, but deriving is just kinda pasting stuff around, like a macro, so it seems okay.
cc #27245