|  | 
| 11 | 11 | //! The compiler code necessary to implement the `#[derive]` extensions. | 
| 12 | 12 | 
 | 
| 13 | 13 | use syntax::ast::{self, MetaItem}; | 
|  | 14 | +use syntax::attr::HasAttrs; | 
| 14 | 15 | use syntax::ext::base::{Annotatable, ExtCtxt}; | 
| 15 | 16 | use syntax::ext::build::AstBuilder; | 
| 16 | 17 | use syntax::feature_gate; | 
| @@ -104,13 +105,37 @@ pub fn expand_derive(cx: &mut ExtCtxt, | 
| 104 | 105 |         } | 
| 105 | 106 |     }; | 
| 106 | 107 | 
 | 
| 107 |  | -    if mitem.value_str().is_some() { | 
| 108 |  | -        cx.span_err(mitem.span, "unexpected value in `derive`"); | 
|  | 108 | +    let mut derive_attrs = Vec::new(); | 
|  | 109 | +    item = item.map_attrs(|attrs| { | 
|  | 110 | +        let partition = attrs.into_iter().partition(|attr| &attr.name() == "derive"); | 
|  | 111 | +        derive_attrs = partition.0; | 
|  | 112 | +        partition.1 | 
|  | 113 | +    }); | 
|  | 114 | + | 
|  | 115 | +    // Expand `#[derive]`s after other attribute macro invocations. | 
|  | 116 | +    if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { | 
|  | 117 | +        return vec![Annotatable::Item(item.map_attrs(|mut attrs| { | 
|  | 118 | +            attrs.push(cx.attribute(span, P(mitem.clone()))); | 
|  | 119 | +            attrs.extend(derive_attrs); | 
|  | 120 | +            attrs | 
|  | 121 | +        }))]; | 
| 109 | 122 |     } | 
| 110 | 123 | 
 | 
| 111 |  | -    let mut traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); | 
| 112 |  | -    if traits.is_empty() { | 
| 113 |  | -        cx.span_warn(mitem.span, "empty trait list in `derive`"); | 
|  | 124 | +    let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| { | 
|  | 125 | +        if mitem.value_str().is_some() { | 
|  | 126 | +            cx.span_err(mitem.span, "unexpected value in `derive`"); | 
|  | 127 | +        } | 
|  | 128 | + | 
|  | 129 | +        let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); | 
|  | 130 | +        if traits.is_empty() { | 
|  | 131 | +            cx.span_warn(mitem.span, "empty trait list in `derive`"); | 
|  | 132 | +        } | 
|  | 133 | +        traits | 
|  | 134 | +    }; | 
|  | 135 | + | 
|  | 136 | +    let mut traits = get_traits(mitem, cx); | 
|  | 137 | +    for derive_attr in derive_attrs { | 
|  | 138 | +        traits.extend(get_traits(&derive_attr.node.value, cx)); | 
| 114 | 139 |     } | 
| 115 | 140 | 
 | 
| 116 | 141 |     // First, weed out malformed #[derive] | 
|  | 
0 commit comments