]> git.lizzy.rs Git - rust.git/commitdiff
Merge branch 'master' into mulit-decor
authorNick Cameron <ncameron@mozilla.com>
Wed, 13 May 2015 03:09:17 +0000 (15:09 +1200)
committerNick Cameron <ncameron@mozilla.com>
Wed, 13 May 2015 03:09:17 +0000 (15:09 +1200)
1  2 
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/expand.rs

index b1ab0438a018b85ba481262af24daadb343a4655,f7511f9753aa18a975c3e702ee5c9f4f267fb2e8..1525f1a822bec5436160b91abb9f9f078383b179
@@@ -197,7 -197,7 +197,7 @@@ use ast::{EnumDef, Expr, Ident, Generic
  use ast_util;
  use attr;
  use attr::AttrMetaMethods;
 -use ext::base::ExtCtxt;
 +use ext::base::{ExtCtxt, Annotatable};
  use ext::build::AstBuilder;
  use codemap::{self, DUMMY_SP};
  use codemap::Span;
@@@ -380,49 -380,41 +380,49 @@@ impl<'a> TraitDef<'a> 
      pub fn expand(&self,
                    cx: &mut ExtCtxt,
                    mitem: &ast::MetaItem,
 -                  item: &'a ast::Item,
 -                  push: &mut FnMut(P<ast::Item>))
 +                  item: &'a Annotatable,
 +                  push: &mut FnMut(Annotatable))
      {
 -        let newitem = match item.node {
 -            ast::ItemStruct(ref struct_def, ref generics) => {
 -                self.expand_struct_def(cx,
 -                                       &**struct_def,
 -                                       item.ident,
 -                                       generics)
 -            }
 -            ast::ItemEnum(ref enum_def, ref generics) => {
 -                self.expand_enum_def(cx,
 -                                     enum_def,
 -                                     &item.attrs[..],
 -                                     item.ident,
 -                                     generics)
 +        match *item {
 +            Annotatable::Item(ref item) => {
 +                let newitem = match item.node {
 +                    ast::ItemStruct(ref struct_def, ref generics) => {
 +                        self.expand_struct_def(cx,
 +                                               &struct_def,
 +                                               item.ident,
 +                                               generics)
 +                    }
 +                    ast::ItemEnum(ref enum_def, ref generics) => {
 +                        self.expand_enum_def(cx,
 +                                             enum_def,
 +                                             &item.attrs,
 +                                             item.ident,
 +                                             generics)
 +                    }
 +                    _ => {
 +                        cx.span_err(mitem.span,
 +                                    "`derive` may only be applied to structs and enums");
 +                        return;
 +                    }
 +                };
 +                // Keep the lint attributes of the previous item to control how the
 +                // generated implementations are linted
 +                let mut attrs = newitem.attrs.clone();
 +                attrs.extend(item.attrs.iter().filter(|a| {
 +                    match &a.name()[..] {
 +                        "allow" | "warn" | "deny" | "forbid" => true,
 +                        _ => false,
 +                    }
 +                }).cloned());
 +                push(Annotatable::Item(P(ast::Item {
 +                    attrs: attrs,
 +                    ..(*newitem).clone()
 +                })))
              }
              _ => {
                  cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");
 -                return;
 -            }
 -        };
 -        // Keep the lint attributes of the previous item to control how the
 -        // generated implementations are linted
 -        let mut attrs = newitem.attrs.clone();
 -        attrs.extend(item.attrs.iter().filter(|a| {
 -            match &a.name()[..] {
 -                "allow" | "warn" | "deny" | "forbid" => true,
 -                _ => false,
              }
 -        }).cloned());
 -        push(P(ast::Item {
 -            attrs: attrs,
 -            ..(*newitem).clone()
 -        }))
 +        }
      }
  
      /// Given that we are deriving a trait `DerivedTrait` for a type like:
@@@ -904,8 -896,8 +904,8 @@@ impl<'a> MethodDef<'a> 
                                   nonself_args: &[P<Expr>])
          -> P<Expr> {
  
-         let mut raw_fields = Vec::new(); // ~[[fields of self],
-                                  // [fields of next Self arg], [etc]]
+         let mut raw_fields = Vec::new(); // Vec<[fields of self],
+                                  // [fields of next Self arg], [etc]>
          let mut patterns = Vec::new();
          for i in 0..self_args.len() {
              let struct_path= cx.path(DUMMY_SP, vec!( type_ident ));
index 476ab0fbf1136cf297864c5105d4272dc541ad7a,05499959b758598f5b83259c5f3b1d86aedab79d..d71557bd7372d6f37a608e2319cc4f664254a53a
@@@ -477,6 -477,58 +477,6 @@@ pub fn expand_item(it: P<ast::Item>, fl
          .into_iter().map(|i| i.expect_item()).collect()
  }
  
 -fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
 -                         -> P<ast::Item> {
 -    // partition the attributes into ItemModifiers and others
 -    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
 -
 -    // update the attrs, leave everything else alone. Is this mutation really a good idea?
 -    it = P(ast::Item {
 -        attrs: other_attrs,
 -        ..(*it).clone()
 -    });
 -
 -    if modifiers.is_empty() {
 -        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
 -        return it.expect_item();
 -    }
 -
 -    for attr in &modifiers {
 -        let mname = attr.name();
 -
 -        match fld.cx.syntax_env.find(&intern(&mname)) {
 -            Some(rc) => match *rc {
 -                Modifier(ref mac) => {
 -                    attr::mark_used(attr);
 -                    fld.cx.bt_push(ExpnInfo {
 -                        call_site: attr.span,
 -                        callee: NameAndSpan {
 -                            name: mname.to_string(),
 -                            format: MacroAttribute,
 -                            span: None,
 -                            // attributes can do whatever they like,
 -                            // for now
 -                            allow_internal_unstable: true,
 -                        }
 -                    });
 -                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
 -                    fld.cx.bt_pop();
 -                }
 -                _ => unreachable!()
 -            },
 -            _ => unreachable!()
 -        }
 -    }
 -
 -    // Expansion may have added new ItemModifiers.
 -    // It is possible, that an item modifier could expand to a multi-modifier or
 -    // vice versa. In this case we will expand all modifiers before multi-modifiers,
 -    // which might give an odd ordering. However, I think it is unlikely that the
 -    // two kinds will be mixed, and I old-style multi-modifiers should be deprecated
 -    // anyway.
 -    expand_item_modifiers(it, fld)
 -}
 -
  /// Expand item_underscore
  fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ {
      match item {
@@@ -1038,7 -1090,48 +1038,7 @@@ fn expand_annotatable(a: Annotatable
  
      let mut decorator_items = SmallVector::zero();
      let mut new_attrs = Vec::new();
 -    for attr in a.attrs() {
 -        let mname = attr.name();
 -
 -        match fld.cx.syntax_env.find(&intern(&mname)) {
 -            Some(rc) => match *rc {
 -                Decorator(ref dec) => {
 -                    let it = match a {
 -                        Annotatable::Item(ref it) => it,
 -                        // ItemDecorators are only implemented for Items.
 -                        _ => break,
 -                    };
 -
 -                    attr::mark_used(attr);
 -
 -                    fld.cx.bt_push(ExpnInfo {
 -                        call_site: attr.span,
 -                        callee: NameAndSpan {
 -                            name: mname.to_string(),
 -                            format: MacroAttribute,
 -                            span: Some(attr.span),
 -                            // attributes can do whatever they like,
 -                            // for now.
 -                            allow_internal_unstable: true,
 -                        }
 -                    });
 -
 -                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
 -                    // but that double-mut-borrows fld
 -                    let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
 -                    dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
 -                               &mut |item| items.push(item));
 -                    decorator_items.extend(
 -                        items.into_iter()
 -                             .flat_map(|item| expand_item(item, fld).into_iter()));
 -
 -                    fld.cx.bt_pop();
 -                }
 -                _ => new_attrs.push((*attr).clone()),
 -            },
 -            _ => new_attrs.push((*attr).clone()),
 -        }
 -    }
 +    expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs);
  
      let mut new_items: SmallVector<Annotatable> = match a {
          Annotatable::Item(it) => match it.node {
          }
      };
  
 -    new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
 +    new_items.push_all(decorator_items);
      new_items
  }
  
 -// partition the attributes into ItemModifiers and others
 -fn modifiers(attrs: &Vec<ast::Attribute>,
 -             fld: &MacroExpander)
 -             -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
 -    attrs.iter().cloned().partition(|attr| {
 -        match fld.cx.syntax_env.find(&intern(&attr.name())) {
 -            Some(rc) => match *rc {
 -                Modifier(_) => true,
 -                _ => false
 -            },
 -            _ => false
 +// Partition a set of attributes into one kind of attribute, and other kinds.
 +macro_rules! partition {
 +    ($fn_name: ident, $variant: ident) => {
 +        #[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used.
 +        fn $fn_name(attrs: &[ast::Attribute],
 +                    fld: &MacroExpander)
 +                     -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
 +            attrs.iter().cloned().partition(|attr| {
 +                match fld.cx.syntax_env.find(&intern(&attr.name())) {
 +                    Some(rc) => match *rc {
 +                        $variant(..) => true,
 +                        _ => false
 +                    },
 +                    _ => false
 +                }
 +            })
          }
 -    })
 +    }
  }
  
 -// partition the attributes into MultiModifiers and others
 -fn multi_modifiers(attrs: &[ast::Attribute],
 -                   fld: &MacroExpander)
 -                   -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
 -    attrs.iter().cloned().partition(|attr| {
 -        match fld.cx.syntax_env.find(&intern(&attr.name())) {
 +partition!(modifiers, Modifier);
 +partition!(multi_modifiers, MultiModifier);
 +
 +
 +#[allow(deprecated)] // The `allow` is needed because the `Decorator` variant is used.
 +fn expand_decorators(a: Annotatable,
 +                     fld: &mut MacroExpander,
 +                     decorator_items: &mut SmallVector<Annotatable>,
 +                     new_attrs: &mut Vec<ast::Attribute>)
 +{
 +    for attr in a.attrs() {
 +        let mname = attr.name();
 +        match fld.cx.syntax_env.find(&intern(&mname)) {
              Some(rc) => match *rc {
 -                MultiModifier(_) => true,
 -                _ => false
 +                Decorator(ref dec) => {
 +                    attr::mark_used(&attr);
 +
 +                    fld.cx.bt_push(ExpnInfo {
 +                        call_site: attr.span,
 +                        callee: NameAndSpan {
 +                            name: mname.to_string(),
 +                            format: MacroAttribute,
 +                            span: Some(attr.span),
 +                            // attributes can do whatever they like,
 +                            // for now.
 +                            allow_internal_unstable: true,
 +                        }
 +                    });
 +
 +                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
 +                    // but that double-mut-borrows fld
 +                    let mut items: SmallVector<Annotatable> = SmallVector::zero();
 +                    dec.expand(fld.cx,
 +                               attr.span,
 +                               &attr.node.value,
 +                               &a.clone().expect_item(),
 +                               &mut |item| items.push(Annotatable::Item(item)));
 +                    decorator_items.extend(items.into_iter()
 +                        .flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
 +
 +                    fld.cx.bt_pop();
 +                }
 +                MultiDecorator(ref dec) => {
 +                    attr::mark_used(&attr);
 +
 +                    fld.cx.bt_push(ExpnInfo {
 +                        call_site: attr.span,
 +                        callee: NameAndSpan {
 +                            name: mname.to_string(),
 +                            format: MacroAttribute,
 +                            span: Some(attr.span),
 +                            // attributes can do whatever they like,
 +                            // for now.
 +                            allow_internal_unstable: true,
 +                        }
 +                    });
 +
 +                    // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
 +                    // but that double-mut-borrows fld
 +                    let mut items: SmallVector<Annotatable> = SmallVector::zero();
 +                    dec.expand(fld.cx,
 +                               attr.span,
 +                               &attr.node.value,
 +                               a.clone(),
 +                               &mut |ann| items.push(ann));
 +                    decorator_items.extend(items.into_iter()
 +                        .flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
 +
 +                    fld.cx.bt_pop();
 +                }
 +                _ => new_attrs.push((*attr).clone()),
              },
 -            _ => false
 +            _ => new_attrs.push((*attr).clone()),
          }
 -    })
 +    }
  }
  
  fn expand_item_multi_modifier(mut it: Annotatable,
                          callee: NameAndSpan {
                              name: mname.to_string(),
                              format: MacroAttribute,
 -                            span: None,
 +                            span: Some(attr.span),
                              // attributes can do whatever they like,
                              // for now
                              allow_internal_unstable: true,
      expand_item_multi_modifier(it, fld)
  }
  
 +#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used
 +fn expand_item_modifiers(mut it: P<ast::Item>,
 +                         fld: &mut MacroExpander)
 +                         -> P<ast::Item> {
 +    // partition the attributes into ItemModifiers and others
 +    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
 +
 +    // update the attrs, leave everything else alone. Is this mutation really a good idea?
 +    it = P(ast::Item {
 +        attrs: other_attrs,
 +        ..(*it).clone()
 +    });
 +
 +    if modifiers.is_empty() {
 +        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
 +        return it.expect_item();
 +    }
 +
 +    for attr in &modifiers {
 +        let mname = attr.name();
 +
 +        match fld.cx.syntax_env.find(&intern(&mname)) {
 +            Some(rc) => match *rc {
 +                Modifier(ref mac) => {
 +                    attr::mark_used(attr);
 +                    fld.cx.bt_push(ExpnInfo {
 +                        call_site: attr.span,
 +                        callee: NameAndSpan {
 +                            name: mname.to_string(),
 +                            format: MacroAttribute,
 +                            span: Some(attr.span),
 +                            // attributes can do whatever they like,
 +                            // for now
 +                            allow_internal_unstable: true,
 +                        }
 +                    });
 +                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
 +                    fld.cx.bt_pop();
 +                }
 +                _ => unreachable!()
 +            },
 +            _ => unreachable!()
 +        }
 +    }
 +
 +    // Expansion may have added new ItemModifiers.
 +    // It is possible, that an item modifier could expand to a multi-modifier or
 +    // vice versa. In this case we will expand all modifiers before multi-modifiers,
 +    // which might give an odd ordering. However, I think it is unlikely that the
 +    // two kinds will be mixed, and old-style multi-modifiers are deprecated.
 +    expand_item_modifiers(it, fld)
 +}
 +
  fn expand_impl_item(ii: P<ast::ImplItem>, fld: &mut MacroExpander)
                   -> SmallVector<P<ast::ImplItem>> {
      match ii.node {
@@@ -1719,7 -1692,7 +1719,7 @@@ mod tests 
      // induced by visit.  Each of these arrays contains a list of indexes,
      // interpreted as the varrefs in the varref traversal that this binding
      // should match.  So, for instance, in a program with two bindings and
-     // three varrefs, the array ~[~[1,2],~[0]] would indicate that the first
+     // three varrefs, the array [[1, 2], [0]] would indicate that the first
      // binding should match the second two varrefs, and the second binding
      // should match the first varref.
      //