Skip to content

Commit

Permalink
Give access to field attributes in ext::deriving
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth committed May 1, 2015
1 parent 8a60e56 commit ede7a6d
Showing 1 changed file with 33 additions and 29 deletions.
62 changes: 33 additions & 29 deletions src/libsyntax/ext/deriving/generic/mod.rs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ pub struct Substructure<'a> {
} }


/// Summary of the relevant parts of a struct/enum field. /// Summary of the relevant parts of a struct/enum field.
pub struct FieldInfo { pub struct FieldInfo<'a> {
pub span: Span, pub span: Span,
/// None for tuple structs/normal enum variants, Some for normal /// None for tuple structs/normal enum variants, Some for normal
/// structs/struct enum variants. /// structs/struct enum variants.
Expand All @@ -281,6 +281,8 @@ pub struct FieldInfo {
/// The expressions corresponding to references to this field in /// The expressions corresponding to references to this field in
/// the other `Self` arguments. /// the other `Self` arguments.
pub other: Vec<P<Expr>>, pub other: Vec<P<Expr>>,
/// The attributes on the field
pub attrs: &'a [ast::Attribute],
} }


/// Fields for a static method /// Fields for a static method
Expand All @@ -293,11 +295,11 @@ pub enum StaticFields {


/// A summary of the possible sets of fields. /// A summary of the possible sets of fields.
pub enum SubstructureFields<'a> { pub enum SubstructureFields<'a> {
Struct(Vec<FieldInfo>), Struct(Vec<FieldInfo<'a>>),
/// Matching variants of the enum: variant index, ast::Variant, /// Matching variants of the enum: variant index, ast::Variant,
/// fields: the field name is only non-`None` in the case of a struct /// fields: the field name is only non-`None` in the case of a struct
/// variant. /// variant.
EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo>), EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),


/// Non-matching variants of the enum, but with all state hidden from /// Non-matching variants of the enum, but with all state hidden from
/// the consequent code. The first component holds `Ident`s for all of /// the consequent code. The first component holds `Ident`s for all of
Expand Down Expand Up @@ -378,7 +380,7 @@ impl<'a> TraitDef<'a> {
pub fn expand(&self, pub fn expand(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
mitem: &ast::MetaItem, mitem: &ast::MetaItem,
item: &ast::Item, item: &'a ast::Item,
push: &mut FnMut(P<ast::Item>)) push: &mut FnMut(P<ast::Item>))
{ {
let newitem = match item.node { let newitem = match item.node {
Expand Down Expand Up @@ -609,7 +611,7 @@ impl<'a> TraitDef<'a> {


fn expand_struct_def(&self, fn expand_struct_def(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
struct_def: &StructDef, struct_def: &'a StructDef,
type_ident: Ident, type_ident: Ident,
generics: &Generics) -> P<ast::Item> { generics: &Generics) -> P<ast::Item> {
let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter() let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter()
Expand Down Expand Up @@ -653,7 +655,7 @@ impl<'a> TraitDef<'a> {


fn expand_enum_def(&self, fn expand_enum_def(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
enum_def: &EnumDef, enum_def: &'a EnumDef,
type_attrs: &[ast::Attribute], type_attrs: &[ast::Attribute],
type_ident: Ident, type_ident: Ident,
generics: &Generics) -> P<ast::Item> { generics: &Generics) -> P<ast::Item> {
Expand Down Expand Up @@ -885,10 +887,10 @@ impl<'a> MethodDef<'a> {
/// } /// }
/// } /// }
/// ``` /// ```
fn expand_struct_method_body(&self, fn expand_struct_method_body<'b>(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
trait_: &TraitDef, trait_: &TraitDef<'b>,
struct_def: &StructDef, struct_def: &'b StructDef,
type_ident: Ident, type_ident: Ident,
self_args: &[P<Expr>], self_args: &[P<Expr>],
nonself_args: &[P<Expr>]) nonself_args: &[P<Expr>])
Expand All @@ -914,18 +916,19 @@ impl<'a> MethodDef<'a> {
let fields = if !raw_fields.is_empty() { let fields = if !raw_fields.is_empty() {
let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter()); let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter());
let first_field = raw_fields.next().unwrap(); let first_field = raw_fields.next().unwrap();
let mut other_fields: Vec<vec::IntoIter<(Span, Option<Ident>, P<Expr>)>> let mut other_fields: Vec<vec::IntoIter<_>>
= raw_fields.collect(); = raw_fields.collect();
first_field.map(|(span, opt_id, field)| { first_field.map(|(span, opt_id, field, attrs)| {
FieldInfo { FieldInfo {
span: span, span: span,
name: opt_id, name: opt_id,
self_: field, self_: field,
other: other_fields.iter_mut().map(|l| { other: other_fields.iter_mut().map(|l| {
match l.next().unwrap() { match l.next().unwrap() {
(_, _, ex) => ex (_, _, ex, _) => ex
} }
}).collect() }).collect(),
attrs: attrs,
} }
}).collect() }).collect()
} else { } else {
Expand Down Expand Up @@ -999,10 +1002,10 @@ impl<'a> MethodDef<'a> {
/// `PartialEq`, and those subcomputations will hopefully be removed /// `PartialEq`, and those subcomputations will hopefully be removed
/// as their results are unused. The point of `__self_vi` and /// as their results are unused. The point of `__self_vi` and
/// `__arg_1_vi` is for `PartialOrd`; see #15503.) /// `__arg_1_vi` is for `PartialOrd`; see #15503.)
fn expand_enum_method_body(&self, fn expand_enum_method_body<'b>(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
trait_: &TraitDef, trait_: &TraitDef<'b>,
enum_def: &EnumDef, enum_def: &'b EnumDef,
type_attrs: &[ast::Attribute], type_attrs: &[ast::Attribute],
type_ident: Ident, type_ident: Ident,
self_args: Vec<P<Expr>>, self_args: Vec<P<Expr>>,
Expand Down Expand Up @@ -1038,11 +1041,11 @@ impl<'a> MethodDef<'a> {
/// } /// }
/// } /// }
/// ``` /// ```
fn build_enum_match_tuple( fn build_enum_match_tuple<'b>(
&self, &self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
trait_: &TraitDef, trait_: &TraitDef<'b>,
enum_def: &EnumDef, enum_def: &'b EnumDef,
type_attrs: &[ast::Attribute], type_attrs: &[ast::Attribute],
type_ident: Ident, type_ident: Ident,
self_args: Vec<P<Expr>>, self_args: Vec<P<Expr>>,
Expand Down Expand Up @@ -1125,15 +1128,15 @@ impl<'a> MethodDef<'a> {
// arg fields of the variant for the first self pat. // arg fields of the variant for the first self pat.
let field_tuples = first_self_pat_idents.into_iter().enumerate() let field_tuples = first_self_pat_idents.into_iter().enumerate()
// For each arg field of self, pull out its getter expr ... // For each arg field of self, pull out its getter expr ...
.map(|(field_index, (sp, opt_ident, self_getter_expr))| { .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| {
// ... but FieldInfo also wants getter expr // ... but FieldInfo also wants getter expr
// for matching other arguments of Self type; // for matching other arguments of Self type;
// so walk across the *other* self_pats_idents // so walk across the *other* self_pats_idents
// and pull out getter for same field in each // and pull out getter for same field in each
// of them (using `field_index` tracked above). // of them (using `field_index` tracked above).
// That is the heart of the transposition. // That is the heart of the transposition.
let others = self_pats_idents.iter().map(|fields| { let others = self_pats_idents.iter().map(|fields| {
let (_, _opt_ident, ref other_getter_expr) = let (_, _opt_ident, ref other_getter_expr, _) =
fields[field_index]; fields[field_index];


// All Self args have same variant, so // All Self args have same variant, so
Expand All @@ -1149,6 +1152,7 @@ impl<'a> MethodDef<'a> {
name: opt_ident, name: opt_ident,
self_: self_getter_expr, self_: self_getter_expr,
other: others, other: others,
attrs: attrs,
} }
}).collect::<Vec<FieldInfo>>(); }).collect::<Vec<FieldInfo>>();


Expand Down Expand Up @@ -1400,10 +1404,10 @@ impl<'a> TraitDef<'a> {
fn create_struct_pattern(&self, fn create_struct_pattern(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
struct_path: ast::Path, struct_path: ast::Path,
struct_def: &StructDef, struct_def: &'a StructDef,
prefix: &str, prefix: &str,
mutbl: ast::Mutability) mutbl: ast::Mutability)
-> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>)>) { -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
if struct_def.fields.is_empty() { if struct_def.fields.is_empty() {
return (cx.pat_enum(self.span, struct_path, vec![]), vec![]); return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
} }
Expand Down Expand Up @@ -1433,15 +1437,15 @@ impl<'a> TraitDef<'a> {
paths.push(codemap::Spanned{span: sp, node: ident}); paths.push(codemap::Spanned{span: sp, node: ident});
let val = cx.expr( let val = cx.expr(
sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident))))); sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
ident_expr.push((sp, opt_id, val)); ident_expr.push((sp, opt_id, val, &struct_field.node.attrs[..]));
} }


let subpats = self.create_subpatterns(cx, paths, mutbl); let subpats = self.create_subpatterns(cx, paths, mutbl);


// struct_type is definitely not Unknown, since struct_def.fields // struct_type is definitely not Unknown, since struct_def.fields
// must be nonempty to reach here // must be nonempty to reach here
let pattern = if struct_type == Record { let pattern = if struct_type == Record {
let field_pats = subpats.into_iter().zip(ident_expr.iter()).map(|(pat, &(_, id, _))| { let field_pats = subpats.into_iter().zip(ident_expr.iter()).map(|(pat, &(_, id, _, _))| {
// id is guaranteed to be Some // id is guaranteed to be Some
codemap::Spanned { codemap::Spanned {
span: pat.span, span: pat.span,
Expand All @@ -1459,10 +1463,10 @@ impl<'a> TraitDef<'a> {
fn create_enum_variant_pattern(&self, fn create_enum_variant_pattern(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
enum_ident: ast::Ident, enum_ident: ast::Ident,
variant: &ast::Variant, variant: &'a ast::Variant,
prefix: &str, prefix: &str,
mutbl: ast::Mutability) mutbl: ast::Mutability)
-> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>)>) { -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
let variant_ident = variant.node.name; let variant_ident = variant.node.name;
let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]); let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]);
match variant.node.kind { match variant.node.kind {
Expand All @@ -1472,15 +1476,15 @@ impl<'a> TraitDef<'a> {
} }


let mut paths = Vec::new(); let mut paths = Vec::new();
let mut ident_expr = Vec::new(); let mut ident_expr: Vec<(_, _, _, &'a [ast::Attribute])> = Vec::new();
for (i, va) in variant_args.iter().enumerate() { for (i, va) in variant_args.iter().enumerate() {
let sp = self.set_expn_info(cx, va.ty.span); let sp = self.set_expn_info(cx, va.ty.span);
let ident = cx.ident_of(&format!("{}_{}", prefix, i)); let ident = cx.ident_of(&format!("{}_{}", prefix, i));
let path1 = codemap::Spanned{span: sp, node: ident}; let path1 = codemap::Spanned{span: sp, node: ident};
paths.push(path1); paths.push(path1);
let expr_path = cx.expr_path(cx.path_ident(sp, ident)); let expr_path = cx.expr_path(cx.path_ident(sp, ident));
let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path))); let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
ident_expr.push((sp, None, val)); ident_expr.push((sp, None, val, &[]));
} }


let subpats = self.create_subpatterns(cx, paths, mutbl); let subpats = self.create_subpatterns(cx, paths, mutbl);
Expand Down

0 comments on commit ede7a6d

Please sign in to comment.