From 640832aa1ceaa445bf6f74b6e2a10f7e2039dc20 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 13:37:09 -0500 Subject: [PATCH 1/8] Separate unsafe blocks into a ExprKind variant --- src/expr.rs | 40 ++++++++++++++++++++++++++++++++-------- src/gen/fold.rs | 15 ++++++++++++++- src/gen/visit.rs | 11 ++++++++++- src/gen/visit_mut.rs | 11 ++++++++++- src/lib.rs | 2 +- tests/test_precedence.rs | 1 + 6 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index df930ba050..a6e7e06843 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -202,9 +202,14 @@ ast_enum_of_structs! { pub or2_token: Token![|], }), - /// A block (`{ ... }` or `unsafe { ... }`) + /// An unsafe block (`unsafe { ... }`) + pub Unsafe(ExprUnsafe #full { + pub unsafe_token: Token![unsafe], + pub block: Block, + }), + + /// A block (`{ ... }`) pub Block(ExprBlock #full { - pub unsafety: Unsafety, pub block: Block, }), @@ -628,6 +633,7 @@ fn arm_expr_requires_comma(expr: &Expr) -> bool { // see https://github.com/rust-lang/rust/blob/eb8f2586e // /src/libsyntax/parse/classify.rs#L17-L37 match expr.node { + ExprKind::Unsafe(..) | ExprKind::Block(..) | ExprKind::If(..) | ExprKind::IfLet(..) | @@ -1192,6 +1198,8 @@ pub mod parsing { | syn!(ExprYield) => { ExprKind::Yield } | + syn!(ExprUnsafe) => { ExprKind::Unsafe } + | call!(expr_closure, allow_struct) | cond_reduce!(allow_block, map!(syn!(ExprBlock), ExprKind::Block)) @@ -1238,6 +1246,8 @@ pub mod parsing { | syn!(ExprYield) => { ExprKind::Yield } | + syn!(ExprUnsafe) => { ExprKind::Unsafe } + | syn!(ExprBlock) => { ExprKind::Block } ), Expr::from)); @@ -1272,7 +1282,6 @@ pub mod parsing { kind: InPlaceKind::In(in_), value: Box::new(Expr { node: ExprBlock { - unsafety: Unsafety::Normal, block: Block { stmts: value.0, brace_token: value.1, @@ -1403,7 +1412,6 @@ pub mod parsing { do_parse!( else_block: braces!(call!(Block::parse_within)) >> (ExprKind::Block(ExprBlock { - unsafety: Unsafety::Normal, block: Block { stmts: else_block.0, brace_token: else_block.1, @@ -1537,7 +1545,6 @@ pub mod parsing { body: syn!(Block) >> (ReturnType::Type(ty, arrow), ExprKind::Block(ExprBlock { - unsafety: Unsafety::Normal, block: body, }).into()) ) @@ -1738,13 +1745,23 @@ pub mod parsing { )); } + #[cfg(feature = "full")] + impl Synom for ExprUnsafe { + named!(parse -> Self, do_parse!( + unsafe_: keyword!(unsafe) >> + b: syn!(Block) >> + (ExprUnsafe { + unsafe_token: unsafe_, + block: b, + }) + )); + } + #[cfg(feature = "full")] impl Synom for ExprBlock { named!(parse -> Self, do_parse!( - rules: syn!(Unsafety) >> b: syn!(Block) >> (ExprBlock { - unsafety: rules, block: b, }) )); @@ -2567,10 +2584,17 @@ mod printing { } } + #[cfg(feature = "full")] + impl ToTokens for ExprUnsafe { + fn to_tokens(&self, tokens: &mut Tokens) { + self.unsafe_token.to_tokens(tokens); + self.block.to_tokens(tokens); + } + } + #[cfg(feature = "full")] impl ToTokens for ExprBlock { fn to_tokens(&self, tokens: &mut Tokens) { - self.unsafety.to_tokens(tokens); self.block.to_tokens(tokens); } } diff --git a/src/gen/fold.rs b/src/gen/fold.rs index 1b676e24a7..b6996f465c 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -176,6 +176,8 @@ fn fold_expr_type(&mut self, i: ExprType) -> ExprType { fold_expr_type(self, i) fn fold_expr_unary(&mut self, i: ExprUnary) -> ExprUnary { fold_expr_unary(self, i) } # [ cfg ( feature = "full" ) ] +fn fold_expr_unsafe(&mut self, i: ExprUnsafe) -> ExprUnsafe { fold_expr_unsafe(self, i) } +# [ cfg ( feature = "full" ) ] fn fold_expr_while(&mut self, i: ExprWhile) -> ExprWhile { fold_expr_while(self, i) } # [ cfg ( feature = "full" ) ] fn fold_expr_while_let(&mut self, i: ExprWhileLet) -> ExprWhileLet { fold_expr_while_let(self, i) } @@ -833,7 +835,6 @@ pub fn fold_expr_binary(_visitor: &mut V, _i: ExprBinary) -> # [ cfg ( feature = "full" ) ] pub fn fold_expr_block(_visitor: &mut V, _i: ExprBlock) -> ExprBlock { ExprBlock { - unsafety: _visitor.fold_unsafety(_i . unsafety), block: _visitor.fold_block(_i . block), } } @@ -1058,6 +1059,11 @@ pub fn fold_expr_kind(_visitor: &mut V, _i: ExprKind) -> Exp full!(_visitor.fold_expr_closure(_binding_0)), ) } + Unsafe(_binding_0, ) => { + Unsafe ( + full!(_visitor.fold_expr_unsafe(_binding_0)), + ) + } Block(_binding_0, ) => { Block ( full!(_visitor.fold_expr_block(_binding_0)), @@ -1279,6 +1285,13 @@ pub fn fold_expr_unary(_visitor: &mut V, _i: ExprUnary) -> E } } # [ cfg ( feature = "full" ) ] +pub fn fold_expr_unsafe(_visitor: &mut V, _i: ExprUnsafe) -> ExprUnsafe { + ExprUnsafe { + unsafe_token: _i . unsafe_token, + block: _visitor.fold_block(_i . block), + } +} +# [ cfg ( feature = "full" ) ] pub fn fold_expr_while(_visitor: &mut V, _i: ExprWhile) -> ExprWhile { ExprWhile { cond: Box::new(_visitor.fold_expr(* _i . cond)), diff --git a/src/gen/visit.rs b/src/gen/visit.rs index da068a156e..ec40662c96 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -149,6 +149,8 @@ fn visit_expr_type(&mut self, i: &'ast ExprType) { visit_expr_type(self, i) } fn visit_expr_unary(&mut self, i: &'ast ExprUnary) { visit_expr_unary(self, i) } # [ cfg ( feature = "full" ) ] +fn visit_expr_unsafe(&mut self, i: &'ast ExprUnsafe) { visit_expr_unsafe(self, i) } +# [ cfg ( feature = "full" ) ] fn visit_expr_while(&mut self, i: &'ast ExprWhile) { visit_expr_while(self, i) } # [ cfg ( feature = "full" ) ] fn visit_expr_while_let(&mut self, i: &'ast ExprWhileLet) { visit_expr_while_let(self, i) } @@ -687,7 +689,6 @@ pub fn visit_expr_binary<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: } # [ cfg ( feature = "full" ) ] pub fn visit_expr_block<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBlock) { - _visitor.visit_unsafety(&_i . unsafety); _visitor.visit_block(&_i . block); } # [ cfg ( feature = "full" ) ] @@ -845,6 +846,9 @@ pub fn visit_expr_kind<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &' Closure(ref _binding_0, ) => { full!(_visitor.visit_expr_closure(&* _binding_0)); } + Unsafe(ref _binding_0, ) => { + full!(_visitor.visit_expr_unsafe(&* _binding_0)); + } Block(ref _binding_0, ) => { full!(_visitor.visit_expr_block(&* _binding_0)); } @@ -998,6 +1002,11 @@ pub fn visit_expr_unary<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: & _visitor.visit_expr(&_i . expr); } # [ cfg ( feature = "full" ) ] +pub fn visit_expr_unsafe<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprUnsafe) { + // Skipped field _i . unsafe_token; + _visitor.visit_block(&_i . block); +} +# [ cfg ( feature = "full" ) ] pub fn visit_expr_while<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprWhile) { _visitor.visit_expr(&_i . cond); _visitor.visit_block(&_i . body); diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 7d5c109e82..80329b057f 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -149,6 +149,8 @@ fn visit_expr_type_mut(&mut self, i: &mut ExprType) { visit_expr_type_mut(self, fn visit_expr_unary_mut(&mut self, i: &mut ExprUnary) { visit_expr_unary_mut(self, i) } # [ cfg ( feature = "full" ) ] +fn visit_expr_unsafe_mut(&mut self, i: &mut ExprUnsafe) { visit_expr_unsafe_mut(self, i) } +# [ cfg ( feature = "full" ) ] fn visit_expr_while_mut(&mut self, i: &mut ExprWhile) { visit_expr_while_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_expr_while_let_mut(&mut self, i: &mut ExprWhileLet) { visit_expr_while_let_mut(self, i) } @@ -687,7 +689,6 @@ pub fn visit_expr_binary_mut(_visitor: &mut V, _i: &mut } # [ cfg ( feature = "full" ) ] pub fn visit_expr_block_mut(_visitor: &mut V, _i: &mut ExprBlock) { - _visitor.visit_unsafety_mut(&mut _i . unsafety); _visitor.visit_block_mut(&mut _i . block); } # [ cfg ( feature = "full" ) ] @@ -845,6 +846,9 @@ pub fn visit_expr_kind_mut(_visitor: &mut V, _i: &mut Ex Closure(ref mut _binding_0, ) => { full!(_visitor.visit_expr_closure_mut(&mut * _binding_0)); } + Unsafe(ref mut _binding_0, ) => { + full!(_visitor.visit_expr_unsafe_mut(&mut * _binding_0)); + } Block(ref mut _binding_0, ) => { full!(_visitor.visit_expr_block_mut(&mut * _binding_0)); } @@ -998,6 +1002,11 @@ pub fn visit_expr_unary_mut(_visitor: &mut V, _i: &mut E _visitor.visit_expr_mut(&mut _i . expr); } # [ cfg ( feature = "full" ) ] +pub fn visit_expr_unsafe_mut(_visitor: &mut V, _i: &mut ExprUnsafe) { + // Skipped field _i . unsafe_token; + _visitor.visit_block_mut(&mut _i . block); +} +# [ cfg ( feature = "full" ) ] pub fn visit_expr_while_mut(_visitor: &mut V, _i: &mut ExprWhile) { _visitor.visit_expr_mut(&mut _i . cond); _visitor.visit_block_mut(&mut _i . body); diff --git a/src/lib.rs b/src/lib.rs index 54f89e91a3..f88112db0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ pub use expr::{Expr, ExprKind, ExprBox, ExprInPlace, ExprArray, ExprCall, ExprAssign, ExprAssignOp, ExprField, ExprTupField, ExprIndex, ExprRange, ExprPath, ExprAddrOf, ExprBreak, ExprContinue, ExprRet, ExprStruct, ExprRepeat, ExprParen, ExprTry, ExprCatch, - ExprGroup, ExprYield}; + ExprGroup, ExprYield, ExprUnsafe}; #[cfg(feature = "full")] pub use expr::{Arm, BindingMode, Block, CaptureBy, FieldPat, FieldValue, Local, diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs index bbc60234cf..171bf4b7b4 100644 --- a/tests/test_precedence.rs +++ b/tests/test_precedence.rs @@ -322,6 +322,7 @@ fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr { ExprKind::Group(_) => unreachable!(), ExprKind::Paren(p) => paren(self, p.expr.node), ExprKind::If(..) | + ExprKind::Unsafe(..) | ExprKind::Block(..) | ExprKind::IfLet(..) => { return fold_expr(self, expr); From 3aa0dc7e0c9cd7c3f66542965d7c9760264e70dc Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 13:41:28 -0500 Subject: [PATCH 2/8] Add an explicit precedence test --- tests/test_precedence.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs index 171bf4b7b4..0d5f5160f4 100644 --- a/tests/test_precedence.rs +++ b/tests/test_precedence.rs @@ -45,6 +45,7 @@ fn test_simple_precedence() { "{ for i in r { } *some_ptr += 1; }", "{ loop { break 5; } }", "{ if true { () }.mthd() }", + "{ for i in unsafe { 20 } { } }", ]; let mut failed = 0; From c691cb4fac9fbbb0c297089490a571a5fe58c571 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 13:44:38 -0500 Subject: [PATCH 3/8] typo --- src/generics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generics.rs b/src/generics.rs index 08dba3902e..f9fa655265 100644 --- a/src/generics.rs +++ b/src/generics.rs @@ -301,7 +301,7 @@ pub mod parsing { )); fn description() -> Option<&'static str> { - Some("type parameter buond") + Some("type parameter bound") } } From 357885acd3f63878eeaed8da00dbbf512cec7e49 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 15:47:07 -0500 Subject: [PATCH 4/8] Update generic arguments to be stored similar to generic parameters --- src/gen/fold.rs | 27 ++++++++- src/gen/visit.rs | 21 ++++++- src/gen/visit_mut.rs | 21 ++++++- src/lib.rs | 2 +- src/ty.rs | 109 ++++++++++++++++++------------------- syn_codegen/src/main.rs | 5 +- tests/test_derive_input.rs | 12 ++-- 7 files changed, 125 insertions(+), 72 deletions(-) diff --git a/src/gen/fold.rs b/src/gen/fold.rs index b6996f465c..6b61cccdc9 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -204,6 +204,8 @@ fn fold_foreign_item_static(&mut self, i: ForeignItemStatic) -> ForeignItemStati # [ cfg ( feature = "full" ) ] fn fold_foreign_item_type(&mut self, i: ForeignItemType) -> ForeignItemType { fold_foreign_item_type(self, i) } +fn fold_generic_arg(&mut self, i: GenericArg) -> GenericArg { fold_generic_arg(self, i) } + fn fold_generic_param(&mut self, i: GenericParam) -> GenericParam { fold_generic_param(self, i) } fn fold_generics(&mut self, i: Generics) -> Generics { fold_generics(self, i) } @@ -428,9 +430,7 @@ pub fn fold_angle_bracketed_parameter_data(_visitor: &mut V, AngleBracketedParameterData { turbofish: _i . turbofish, lt_token: _i . lt_token, - lifetimes: _i . lifetimes, - types: FoldHelper::lift(_i . types, |it| { _visitor.fold_type(it) }), - bindings: FoldHelper::lift(_i . bindings, |it| { _visitor.fold_type_binding(it) }), + args: FoldHelper::lift(_i . args, |it| { _visitor.fold_generic_arg(it) }), gt_token: _i . gt_token, } } @@ -1452,6 +1452,27 @@ pub fn fold_foreign_item_type(_visitor: &mut V, _i: ForeignI } } +pub fn fold_generic_arg(_visitor: &mut V, _i: GenericArg) -> GenericArg { + use ::GenericArg::*; + match _i { + Lifetime(_binding_0, ) => { + Lifetime ( + _binding_0, + ) + } + Type(_binding_0, ) => { + Type ( + _visitor.fold_type(_binding_0), + ) + } + TypeBinding(_binding_0, ) => { + TypeBinding ( + _visitor.fold_type_binding(_binding_0), + ) + } + } +} + pub fn fold_generic_param(_visitor: &mut V, _i: GenericParam) -> GenericParam { use ::GenericParam::*; match _i { diff --git a/src/gen/visit.rs b/src/gen/visit.rs index ec40662c96..72f28612c8 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -177,6 +177,8 @@ fn visit_foreign_item_static(&mut self, i: &'ast ForeignItemStatic) { visit_fore # [ cfg ( feature = "full" ) ] fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) { visit_foreign_item_type(self, i) } +fn visit_generic_arg(&mut self, i: &'ast GenericArg) { visit_generic_arg(self, i) } + fn visit_generic_param(&mut self, i: &'ast GenericParam) { visit_generic_param(self, i) } fn visit_generics(&mut self, i: &'ast Generics) { visit_generics(self, i) } @@ -396,9 +398,7 @@ pub fn visit_abi_kind<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'a pub fn visit_angle_bracketed_parameter_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast AngleBracketedParameterData) { // Skipped field _i . turbofish; // Skipped field _i . lt_token; - // Skipped field _i . lifetimes; - for el in (_i . types).iter() { let it = el.item(); _visitor.visit_type(&it) }; - for el in (_i . bindings).iter() { let it = el.item(); _visitor.visit_type_binding(&it) }; + for el in (_i . args).iter() { let it = el.item(); _visitor.visit_generic_arg(&it) }; // Skipped field _i . gt_token; } # [ cfg ( feature = "full" ) ] @@ -1131,6 +1131,21 @@ pub fn visit_foreign_item_type<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V // Skipped field _i . semi_token; } +pub fn visit_generic_arg<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericArg) { + use ::GenericArg::*; + match *_i { + Lifetime(ref _binding_0, ) => { + // Skipped field * _binding_0; + } + Type(ref _binding_0, ) => { + _visitor.visit_type(&* _binding_0); + } + TypeBinding(ref _binding_0, ) => { + _visitor.visit_type_binding(&* _binding_0); + } + } +} + pub fn visit_generic_param<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericParam) { use ::GenericParam::*; match *_i { diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 80329b057f..2a4cb1197f 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -177,6 +177,8 @@ fn visit_foreign_item_static_mut(&mut self, i: &mut ForeignItemStatic) { visit_f # [ cfg ( feature = "full" ) ] fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) { visit_foreign_item_type_mut(self, i) } +fn visit_generic_arg_mut(&mut self, i: &mut GenericArg) { visit_generic_arg_mut(self, i) } + fn visit_generic_param_mut(&mut self, i: &mut GenericParam) { visit_generic_param_mut(self, i) } fn visit_generics_mut(&mut self, i: &mut Generics) { visit_generics_mut(self, i) } @@ -396,9 +398,7 @@ pub fn visit_abi_kind_mut(_visitor: &mut V, _i: &mut Abi pub fn visit_angle_bracketed_parameter_data_mut(_visitor: &mut V, _i: &mut AngleBracketedParameterData) { // Skipped field _i . turbofish; // Skipped field _i . lt_token; - // Skipped field _i . lifetimes; - for mut el in (_i . types).iter_mut() { let mut it = el.item_mut(); _visitor.visit_type_mut(&mut it) }; - for mut el in (_i . bindings).iter_mut() { let mut it = el.item_mut(); _visitor.visit_type_binding_mut(&mut it) }; + for mut el in (_i . args).iter_mut() { let mut it = el.item_mut(); _visitor.visit_generic_arg_mut(&mut it) }; // Skipped field _i . gt_token; } # [ cfg ( feature = "full" ) ] @@ -1131,6 +1131,21 @@ pub fn visit_foreign_item_type_mut(_visitor: &mut V, _i: // Skipped field _i . semi_token; } +pub fn visit_generic_arg_mut(_visitor: &mut V, _i: &mut GenericArg) { + use ::GenericArg::*; + match *_i { + Lifetime(ref mut _binding_0, ) => { + // Skipped field * _binding_0; + } + Type(ref mut _binding_0, ) => { + _visitor.visit_type_mut(&mut * _binding_0); + } + TypeBinding(ref mut _binding_0, ) => { + _visitor.visit_type_binding_mut(&mut * _binding_0); + } + } +} + pub fn visit_generic_param_mut(_visitor: &mut V, _i: &mut GenericParam) { use ::GenericParam::*; match *_i { diff --git a/src/lib.rs b/src/lib.rs index f88112db0d..bd59686d2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,7 +87,7 @@ pub use ty::{Abi, AbiKind, AngleBracketedParameterData, BareFnArg, BareFnArgName ReturnType, MutType, Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment, PolyTraitRef, QSelf, Type, TypeBinding, Unsafety, TypeSlice, TypeArray, TypePtr, TypeReference, TypeBareFn, TypeNever, TypeTup, TypePath, - TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, TypeGroup}; + TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, TypeGroup, GenericArg}; #[cfg(feature = "printing")] pub use ty::PathTokens; diff --git a/src/ty.rs b/src/ty.rs index 009e081127..77a43fb9f0 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -184,28 +184,32 @@ impl PathParameters { pub fn is_empty(&self) -> bool { match *self { PathParameters::None => true, - PathParameters::AngleBracketed(ref bracketed) => { - bracketed.lifetimes.is_empty() && bracketed.types.is_empty() && - bracketed.bindings.is_empty() - } + PathParameters::AngleBracketed(ref bracketed) => bracketed.args.is_empty(), PathParameters::Parenthesized(_) => false, } } } -ast_struct! { - /// A path like `Foo<'a, T>` - pub struct AngleBracketedParameterData { - pub turbofish: Option, - pub lt_token: Token![<], +ast_enum! { + /// A individual generic argument, like `'a`, `T`, or `Item=T`. + pub enum GenericArg { /// The lifetime parameters for this path segment. - pub lifetimes: Delimited, + Lifetime(Lifetime), /// The type parameters for this path segment, if present. - pub types: Delimited, + Type(Type), /// Bindings (equality constraints) on associated types, if present. /// /// E.g., `Foo`. - pub bindings: Delimited, + TypeBinding(TypeBinding), + } +} + +ast_struct! { + /// A path like `Foo<'a, T>` + pub struct AngleBracketedParameterData { + pub turbofish: Option, + pub lt_token: Token![<], + pub args: Delimited, pub gt_token: Token![>], } } @@ -687,38 +691,39 @@ pub mod parsing { } } + impl Synom for GenericArg { + named!(parse -> Self, alt!( + call!(ty_no_eq_after) => { GenericArg::Type } + | + syn!(Lifetime) => { GenericArg::Lifetime } + | + syn!(TypeBinding) => { GenericArg::TypeBinding } + )); + } + + impl Synom for AngleBracketedParameterData { + named!(parse -> Self, do_parse!( + turbofish: option!(punct!(::)) >> + lt: punct!(<) >> + args: call!(Delimited::parse_terminated) >> + gt: punct!(>) >> + (AngleBracketedParameterData { + turbofish: turbofish, + lt_token: lt, + args: args, + gt_token: gt, + }) + )); + } + impl Synom for PathSegment { named!(parse -> Self, alt!( do_parse!( ident: syn!(Ident) >> - turbofish: option!(punct!(::)) >> - lt: punct!(<) >> - lifetimes: call!(Delimited::parse_terminated) >> - types: cond!( - lifetimes.is_empty() || lifetimes.trailing_delim(), - call!(Delimited::parse_terminated_with, - ty_no_eq_after) - ) >> - bindings: cond!( - match types { - Some(ref t) => t.is_empty() || t.trailing_delim(), - None => lifetimes.is_empty() || lifetimes.trailing_delim(), - }, - call!(Delimited::parse_terminated) - ) >> - gt: punct!(>) >> + parameters: syn!(AngleBracketedParameterData) >> (PathSegment { ident: ident, - parameters: PathParameters::AngleBracketed( - AngleBracketedParameterData { - turbofish: turbofish, - lt_token: lt, - lifetimes: lifetimes, - types: types.unwrap_or_default(), - bindings: bindings.unwrap_or_default(), - gt_token: gt, - } - ), + parameters: PathParameters::AngleBracketed(parameters), }) ) | @@ -1018,27 +1023,21 @@ mod printing { } } + impl ToTokens for GenericArg { + fn to_tokens(&self, tokens: &mut Tokens) { + match *self { + GenericArg::Lifetime(ref lt) => lt.to_tokens(tokens), + GenericArg::Type(ref ty) => ty.to_tokens(tokens), + GenericArg::TypeBinding(ref tb) => tb.to_tokens(tokens), + } + } + } + impl ToTokens for AngleBracketedParameterData { fn to_tokens(&self, tokens: &mut Tokens) { self.turbofish.to_tokens(tokens); self.lt_token.to_tokens(tokens); - self.lifetimes.to_tokens(tokens); - if !self.lifetimes.empty_or_trailing() && !self.types.is_empty() { - ::default().to_tokens(tokens); - } - self.types.to_tokens(tokens); - if ( - // If we have no trailing delimiter after a non-empty types list, or - !self.types.empty_or_trailing() || - // If we have no trailing delimiter after a non-empty lifetimes - // list before an empty types list, and - (self.types.is_empty() && !self.lifetimes.empty_or_trailing())) && - // We have some bindings, then we need a comma. - !self.bindings.is_empty() - { - ::default().to_tokens(tokens); - } - self.bindings.to_tokens(tokens); + self.args.to_tokens(tokens); self.gt_token.to_tokens(tokens); } } diff --git a/syn_codegen/src/main.rs b/syn_codegen/src/main.rs index 412577457f..a1757d29f9 100644 --- a/syn_codegen/src/main.rs +++ b/syn_codegen/src/main.rs @@ -314,7 +314,10 @@ mod codegen { _ => panic!("Expected at least 1 type parameter here"), }; - data.types.first().expect("Expected at least 1 type parameter here").item() + match *data.args.first().expect("Expected at least 1 type parameter here").item() { + &GenericArg::Type(ref ty) => ty, + _ => panic!("Expected at least 1 type parmeter here"), + } } fn simple_visit( diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs index d4e0ada015..c56d59a99b 100644 --- a/tests/test_derive_input.rs +++ b/tests/test_derive_input.rs @@ -118,12 +118,12 @@ fn test_struct() { AngleBracketedParameterData { turbofish: None, lt_token: Default::default(), - lifetimes: Default::default(), - types: vec![Type::from(TypePath { - qself: None, - path: "Attribute".into(), - })].into(), - bindings: Default::default(), + args: vec![ + GenericArg::Type(Type::from(TypePath { + qself: None, + path: "Attribute".into(), + })), + ].into(), gt_token: Default::default(), }, ), From c08227a5f931273195835ff9bf767ecfbd7cf75b Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 16:30:17 -0500 Subject: [PATCH 5/8] Improve the consistency of type naming --- src/gen/fold.rs | 60 +++++++++++------------ src/gen/visit.rs | 48 +++++++++---------- src/gen/visit_mut.rs | 48 +++++++++---------- src/lib.rs | 12 +++-- src/ty.rs | 98 +++++++++++++++++++------------------- syn_codegen/src/main.rs | 18 +++---- tests/test_derive_input.rs | 6 +-- 7 files changed, 146 insertions(+), 144 deletions(-) diff --git a/src/gen/fold.rs b/src/gen/fold.rs index 6b61cccdc9..6a6dddcab3 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -62,7 +62,7 @@ fn fold_abi(&mut self, i: Abi) -> Abi { fold_abi(self, i) } fn fold_abi_kind(&mut self, i: AbiKind) -> AbiKind { fold_abi_kind(self, i) } -fn fold_angle_bracketed_parameter_data(&mut self, i: AngleBracketedParameterData) -> AngleBracketedParameterData { fold_angle_bracketed_parameter_data(self, i) } +fn fold_angle_bracketed_generic_arguments(&mut self, i: AngleBracketedGenericArguments) -> AngleBracketedGenericArguments { fold_angle_bracketed_generic_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn fold_arg_captured(&mut self, i: ArgCaptured) -> ArgCaptured { fold_arg_captured(self, i) } # [ cfg ( feature = "full" ) ] @@ -204,7 +204,7 @@ fn fold_foreign_item_static(&mut self, i: ForeignItemStatic) -> ForeignItemStati # [ cfg ( feature = "full" ) ] fn fold_foreign_item_type(&mut self, i: ForeignItemType) -> ForeignItemType { fold_foreign_item_type(self, i) } -fn fold_generic_arg(&mut self, i: GenericArg) -> GenericArg { fold_generic_arg(self, i) } +fn fold_generic_argument(&mut self, i: GenericArgument) -> GenericArgument { fold_generic_argument(self, i) } fn fold_generic_param(&mut self, i: GenericParam) -> GenericParam { fold_generic_param(self, i) } @@ -278,7 +278,7 @@ fn fold_mutability(&mut self, i: Mutability) -> Mutability { fold_mutability(sel fn fold_nested_meta_item(&mut self, i: NestedMetaItem) -> NestedMetaItem { fold_nested_meta_item(self, i) } -fn fold_parenthesized_parameter_data(&mut self, i: ParenthesizedParameterData) -> ParenthesizedParameterData { fold_parenthesized_parameter_data(self, i) } +fn fold_parenthesized_generic_arguments(&mut self, i: ParenthesizedGenericArguments) -> ParenthesizedGenericArguments { fold_parenthesized_generic_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn fold_pat(&mut self, i: Pat) -> Pat { fold_pat(self, i) } # [ cfg ( feature = "full" ) ] @@ -305,6 +305,8 @@ fn fold_pat_tuple_struct(&mut self, i: PatTupleStruct) -> PatTupleStruct { fold_ fn fold_pat_wild(&mut self, i: PatWild) -> PatWild { fold_pat_wild(self, i) } fn fold_path(&mut self, i: Path) -> Path { fold_path(self, i) } + +fn fold_path_arguments(&mut self, i: PathArguments) -> PathArguments { fold_path_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn fold_path_glob(&mut self, i: PathGlob) -> PathGlob { fold_path_glob(self, i) } # [ cfg ( feature = "full" ) ] @@ -312,8 +314,6 @@ fn fold_path_list(&mut self, i: PathList) -> PathList { fold_path_list(self, i) # [ cfg ( feature = "full" ) ] fn fold_path_list_item(&mut self, i: PathListItem) -> PathListItem { fold_path_list_item(self, i) } -fn fold_path_parameters(&mut self, i: PathParameters) -> PathParameters { fold_path_parameters(self, i) } - fn fold_path_segment(&mut self, i: PathSegment) -> PathSegment { fold_path_segment(self, i) } # [ cfg ( feature = "full" ) ] fn fold_path_simple(&mut self, i: PathSimple) -> PathSimple { fold_path_simple(self, i) } @@ -426,11 +426,11 @@ pub fn fold_abi_kind(_visitor: &mut V, _i: AbiKind) -> AbiKi } } -pub fn fold_angle_bracketed_parameter_data(_visitor: &mut V, _i: AngleBracketedParameterData) -> AngleBracketedParameterData { - AngleBracketedParameterData { +pub fn fold_angle_bracketed_generic_arguments(_visitor: &mut V, _i: AngleBracketedGenericArguments) -> AngleBracketedGenericArguments { + AngleBracketedGenericArguments { turbofish: _i . turbofish, lt_token: _i . lt_token, - args: FoldHelper::lift(_i . args, |it| { _visitor.fold_generic_arg(it) }), + args: FoldHelper::lift(_i . args, |it| { _visitor.fold_generic_argument(it) }), gt_token: _i . gt_token, } } @@ -1452,8 +1452,8 @@ pub fn fold_foreign_item_type(_visitor: &mut V, _i: ForeignI } } -pub fn fold_generic_arg(_visitor: &mut V, _i: GenericArg) -> GenericArg { - use ::GenericArg::*; +pub fn fold_generic_argument(_visitor: &mut V, _i: GenericArgument) -> GenericArgument { + use ::GenericArgument::*; match _i { Lifetime(_binding_0, ) => { Lifetime ( @@ -1985,8 +1985,8 @@ pub fn fold_nested_meta_item(_visitor: &mut V, _i: NestedMet } } -pub fn fold_parenthesized_parameter_data(_visitor: &mut V, _i: ParenthesizedParameterData) -> ParenthesizedParameterData { - ParenthesizedParameterData { +pub fn fold_parenthesized_generic_arguments(_visitor: &mut V, _i: ParenthesizedGenericArguments) -> ParenthesizedGenericArguments { + ParenthesizedGenericArguments { paren_token: _i . paren_token, inputs: FoldHelper::lift(_i . inputs, |it| { _visitor.fold_type(it) }), output: _visitor.fold_return_type(_i . output), @@ -2153,6 +2153,23 @@ pub fn fold_path(_visitor: &mut V, _i: Path) -> Path { segments: FoldHelper::lift(_i . segments, |it| { _visitor.fold_path_segment(it) }), } } + +pub fn fold_path_arguments(_visitor: &mut V, _i: PathArguments) -> PathArguments { + use ::PathArguments::*; + match _i { + None => { None } + AngleBracketed(_binding_0, ) => { + AngleBracketed ( + _visitor.fold_angle_bracketed_generic_arguments(_binding_0), + ) + } + Parenthesized(_binding_0, ) => { + Parenthesized ( + _visitor.fold_parenthesized_generic_arguments(_binding_0), + ) + } + } +} # [ cfg ( feature = "full" ) ] pub fn fold_path_glob(_visitor: &mut V, _i: PathGlob) -> PathGlob { PathGlob { @@ -2179,27 +2196,10 @@ pub fn fold_path_list_item(_visitor: &mut V, _i: PathListIte } } -pub fn fold_path_parameters(_visitor: &mut V, _i: PathParameters) -> PathParameters { - use ::PathParameters::*; - match _i { - None => { None } - AngleBracketed(_binding_0, ) => { - AngleBracketed ( - _visitor.fold_angle_bracketed_parameter_data(_binding_0), - ) - } - Parenthesized(_binding_0, ) => { - Parenthesized ( - _visitor.fold_parenthesized_parameter_data(_binding_0), - ) - } - } -} - pub fn fold_path_segment(_visitor: &mut V, _i: PathSegment) -> PathSegment { PathSegment { ident: _i . ident, - parameters: _visitor.fold_path_parameters(_i . parameters), + arguments: _visitor.fold_path_arguments(_i . arguments), } } # [ cfg ( feature = "full" ) ] diff --git a/src/gen/visit.rs b/src/gen/visit.rs index 72f28612c8..efe7b47487 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -35,7 +35,7 @@ fn visit_abi(&mut self, i: &'ast Abi) { visit_abi(self, i) } fn visit_abi_kind(&mut self, i: &'ast AbiKind) { visit_abi_kind(self, i) } -fn visit_angle_bracketed_parameter_data(&mut self, i: &'ast AngleBracketedParameterData) { visit_angle_bracketed_parameter_data(self, i) } +fn visit_angle_bracketed_generic_arguments(&mut self, i: &'ast AngleBracketedGenericArguments) { visit_angle_bracketed_generic_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn visit_arg_captured(&mut self, i: &'ast ArgCaptured) { visit_arg_captured(self, i) } # [ cfg ( feature = "full" ) ] @@ -177,7 +177,7 @@ fn visit_foreign_item_static(&mut self, i: &'ast ForeignItemStatic) { visit_fore # [ cfg ( feature = "full" ) ] fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) { visit_foreign_item_type(self, i) } -fn visit_generic_arg(&mut self, i: &'ast GenericArg) { visit_generic_arg(self, i) } +fn visit_generic_argument(&mut self, i: &'ast GenericArgument) { visit_generic_argument(self, i) } fn visit_generic_param(&mut self, i: &'ast GenericParam) { visit_generic_param(self, i) } @@ -251,7 +251,7 @@ fn visit_mutability(&mut self, i: &'ast Mutability) { visit_mutability(self, i) fn visit_nested_meta_item(&mut self, i: &'ast NestedMetaItem) { visit_nested_meta_item(self, i) } -fn visit_parenthesized_parameter_data(&mut self, i: &'ast ParenthesizedParameterData) { visit_parenthesized_parameter_data(self, i) } +fn visit_parenthesized_generic_arguments(&mut self, i: &'ast ParenthesizedGenericArguments) { visit_parenthesized_generic_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn visit_pat(&mut self, i: &'ast Pat) { visit_pat(self, i) } # [ cfg ( feature = "full" ) ] @@ -278,6 +278,8 @@ fn visit_pat_tuple_struct(&mut self, i: &'ast PatTupleStruct) { visit_pat_tuple_ fn visit_pat_wild(&mut self, i: &'ast PatWild) { visit_pat_wild(self, i) } fn visit_path(&mut self, i: &'ast Path) { visit_path(self, i) } + +fn visit_path_arguments(&mut self, i: &'ast PathArguments) { visit_path_arguments(self, i) } # [ cfg ( feature = "full" ) ] fn visit_path_glob(&mut self, i: &'ast PathGlob) { visit_path_glob(self, i) } # [ cfg ( feature = "full" ) ] @@ -285,8 +287,6 @@ fn visit_path_list(&mut self, i: &'ast PathList) { visit_path_list(self, i) } # [ cfg ( feature = "full" ) ] fn visit_path_list_item(&mut self, i: &'ast PathListItem) { visit_path_list_item(self, i) } -fn visit_path_parameters(&mut self, i: &'ast PathParameters) { visit_path_parameters(self, i) } - fn visit_path_segment(&mut self, i: &'ast PathSegment) { visit_path_segment(self, i) } # [ cfg ( feature = "full" ) ] fn visit_path_simple(&mut self, i: &'ast PathSimple) { visit_path_simple(self, i) } @@ -395,10 +395,10 @@ pub fn visit_abi_kind<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'a } } -pub fn visit_angle_bracketed_parameter_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast AngleBracketedParameterData) { +pub fn visit_angle_bracketed_generic_arguments<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast AngleBracketedGenericArguments) { // Skipped field _i . turbofish; // Skipped field _i . lt_token; - for el in (_i . args).iter() { let it = el.item(); _visitor.visit_generic_arg(&it) }; + for el in (_i . args).iter() { let it = el.item(); _visitor.visit_generic_argument(&it) }; // Skipped field _i . gt_token; } # [ cfg ( feature = "full" ) ] @@ -1131,8 +1131,8 @@ pub fn visit_foreign_item_type<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V // Skipped field _i . semi_token; } -pub fn visit_generic_arg<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericArg) { - use ::GenericArg::*; +pub fn visit_generic_argument<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericArgument) { + use ::GenericArgument::*; match *_i { Lifetime(ref _binding_0, ) => { // Skipped field * _binding_0; @@ -1542,7 +1542,7 @@ pub fn visit_nested_meta_item<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, } } -pub fn visit_parenthesized_parameter_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ParenthesizedParameterData) { +pub fn visit_parenthesized_generic_arguments<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ParenthesizedGenericArguments) { // Skipped field _i . paren_token; for el in (_i . inputs).iter() { let it = el.item(); _visitor.visit_type(&it) }; _visitor.visit_return_type(&_i . output); @@ -1660,6 +1660,19 @@ pub fn visit_path<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast P // Skipped field _i . leading_colon; for el in (_i . segments).iter() { let it = el.item(); _visitor.visit_path_segment(&it) }; } + +pub fn visit_path_arguments<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathArguments) { + use ::PathArguments::*; + match *_i { + None => { } + AngleBracketed(ref _binding_0, ) => { + _visitor.visit_angle_bracketed_generic_arguments(&* _binding_0); + } + Parenthesized(ref _binding_0, ) => { + _visitor.visit_parenthesized_generic_arguments(&* _binding_0); + } + } +} # [ cfg ( feature = "full" ) ] pub fn visit_path_glob<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathGlob) { _visitor.visit_path(&_i . path); @@ -1680,22 +1693,9 @@ pub fn visit_path_list_item<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _ // Skipped field _i . as_token; } -pub fn visit_path_parameters<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathParameters) { - use ::PathParameters::*; - match *_i { - None => { } - AngleBracketed(ref _binding_0, ) => { - _visitor.visit_angle_bracketed_parameter_data(&* _binding_0); - } - Parenthesized(ref _binding_0, ) => { - _visitor.visit_parenthesized_parameter_data(&* _binding_0); - } - } -} - pub fn visit_path_segment<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathSegment) { // Skipped field _i . ident; - _visitor.visit_path_parameters(&_i . parameters); + _visitor.visit_path_arguments(&_i . arguments); } # [ cfg ( feature = "full" ) ] pub fn visit_path_simple<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathSimple) { diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 2a4cb1197f..77eaaca44e 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -35,7 +35,7 @@ fn visit_abi_mut(&mut self, i: &mut Abi) { visit_abi_mut(self, i) } fn visit_abi_kind_mut(&mut self, i: &mut AbiKind) { visit_abi_kind_mut(self, i) } -fn visit_angle_bracketed_parameter_data_mut(&mut self, i: &mut AngleBracketedParameterData) { visit_angle_bracketed_parameter_data_mut(self, i) } +fn visit_angle_bracketed_generic_arguments_mut(&mut self, i: &mut AngleBracketedGenericArguments) { visit_angle_bracketed_generic_arguments_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_arg_captured_mut(&mut self, i: &mut ArgCaptured) { visit_arg_captured_mut(self, i) } # [ cfg ( feature = "full" ) ] @@ -177,7 +177,7 @@ fn visit_foreign_item_static_mut(&mut self, i: &mut ForeignItemStatic) { visit_f # [ cfg ( feature = "full" ) ] fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) { visit_foreign_item_type_mut(self, i) } -fn visit_generic_arg_mut(&mut self, i: &mut GenericArg) { visit_generic_arg_mut(self, i) } +fn visit_generic_argument_mut(&mut self, i: &mut GenericArgument) { visit_generic_argument_mut(self, i) } fn visit_generic_param_mut(&mut self, i: &mut GenericParam) { visit_generic_param_mut(self, i) } @@ -251,7 +251,7 @@ fn visit_mutability_mut(&mut self, i: &mut Mutability) { visit_mutability_mut(se fn visit_nested_meta_item_mut(&mut self, i: &mut NestedMetaItem) { visit_nested_meta_item_mut(self, i) } -fn visit_parenthesized_parameter_data_mut(&mut self, i: &mut ParenthesizedParameterData) { visit_parenthesized_parameter_data_mut(self, i) } +fn visit_parenthesized_generic_arguments_mut(&mut self, i: &mut ParenthesizedGenericArguments) { visit_parenthesized_generic_arguments_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_pat_mut(&mut self, i: &mut Pat) { visit_pat_mut(self, i) } # [ cfg ( feature = "full" ) ] @@ -278,6 +278,8 @@ fn visit_pat_tuple_struct_mut(&mut self, i: &mut PatTupleStruct) { visit_pat_tup fn visit_pat_wild_mut(&mut self, i: &mut PatWild) { visit_pat_wild_mut(self, i) } fn visit_path_mut(&mut self, i: &mut Path) { visit_path_mut(self, i) } + +fn visit_path_arguments_mut(&mut self, i: &mut PathArguments) { visit_path_arguments_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_path_glob_mut(&mut self, i: &mut PathGlob) { visit_path_glob_mut(self, i) } # [ cfg ( feature = "full" ) ] @@ -285,8 +287,6 @@ fn visit_path_list_mut(&mut self, i: &mut PathList) { visit_path_list_mut(self, # [ cfg ( feature = "full" ) ] fn visit_path_list_item_mut(&mut self, i: &mut PathListItem) { visit_path_list_item_mut(self, i) } -fn visit_path_parameters_mut(&mut self, i: &mut PathParameters) { visit_path_parameters_mut(self, i) } - fn visit_path_segment_mut(&mut self, i: &mut PathSegment) { visit_path_segment_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_path_simple_mut(&mut self, i: &mut PathSimple) { visit_path_simple_mut(self, i) } @@ -395,10 +395,10 @@ pub fn visit_abi_kind_mut(_visitor: &mut V, _i: &mut Abi } } -pub fn visit_angle_bracketed_parameter_data_mut(_visitor: &mut V, _i: &mut AngleBracketedParameterData) { +pub fn visit_angle_bracketed_generic_arguments_mut(_visitor: &mut V, _i: &mut AngleBracketedGenericArguments) { // Skipped field _i . turbofish; // Skipped field _i . lt_token; - for mut el in (_i . args).iter_mut() { let mut it = el.item_mut(); _visitor.visit_generic_arg_mut(&mut it) }; + for mut el in (_i . args).iter_mut() { let mut it = el.item_mut(); _visitor.visit_generic_argument_mut(&mut it) }; // Skipped field _i . gt_token; } # [ cfg ( feature = "full" ) ] @@ -1131,8 +1131,8 @@ pub fn visit_foreign_item_type_mut(_visitor: &mut V, _i: // Skipped field _i . semi_token; } -pub fn visit_generic_arg_mut(_visitor: &mut V, _i: &mut GenericArg) { - use ::GenericArg::*; +pub fn visit_generic_argument_mut(_visitor: &mut V, _i: &mut GenericArgument) { + use ::GenericArgument::*; match *_i { Lifetime(ref mut _binding_0, ) => { // Skipped field * _binding_0; @@ -1542,7 +1542,7 @@ pub fn visit_nested_meta_item_mut(_visitor: &mut V, _i: } } -pub fn visit_parenthesized_parameter_data_mut(_visitor: &mut V, _i: &mut ParenthesizedParameterData) { +pub fn visit_parenthesized_generic_arguments_mut(_visitor: &mut V, _i: &mut ParenthesizedGenericArguments) { // Skipped field _i . paren_token; for mut el in (_i . inputs).iter_mut() { let mut it = el.item_mut(); _visitor.visit_type_mut(&mut it) }; _visitor.visit_return_type_mut(&mut _i . output); @@ -1660,6 +1660,19 @@ pub fn visit_path_mut(_visitor: &mut V, _i: &mut Path) { // Skipped field _i . leading_colon; for mut el in (_i . segments).iter_mut() { let mut it = el.item_mut(); _visitor.visit_path_segment_mut(&mut it) }; } + +pub fn visit_path_arguments_mut(_visitor: &mut V, _i: &mut PathArguments) { + use ::PathArguments::*; + match *_i { + None => { } + AngleBracketed(ref mut _binding_0, ) => { + _visitor.visit_angle_bracketed_generic_arguments_mut(&mut * _binding_0); + } + Parenthesized(ref mut _binding_0, ) => { + _visitor.visit_parenthesized_generic_arguments_mut(&mut * _binding_0); + } + } +} # [ cfg ( feature = "full" ) ] pub fn visit_path_glob_mut(_visitor: &mut V, _i: &mut PathGlob) { _visitor.visit_path_mut(&mut _i . path); @@ -1680,22 +1693,9 @@ pub fn visit_path_list_item_mut(_visitor: &mut V, _i: &m // Skipped field _i . as_token; } -pub fn visit_path_parameters_mut(_visitor: &mut V, _i: &mut PathParameters) { - use ::PathParameters::*; - match *_i { - None => { } - AngleBracketed(ref mut _binding_0, ) => { - _visitor.visit_angle_bracketed_parameter_data_mut(&mut * _binding_0); - } - Parenthesized(ref mut _binding_0, ) => { - _visitor.visit_parenthesized_parameter_data_mut(&mut * _binding_0); - } - } -} - pub fn visit_path_segment_mut(_visitor: &mut V, _i: &mut PathSegment) { // Skipped field _i . ident; - _visitor.visit_path_parameters_mut(&mut _i . parameters); + _visitor.visit_path_arguments_mut(&mut _i . arguments); } # [ cfg ( feature = "full" ) ] pub fn visit_path_simple_mut(_visitor: &mut V, _i: &mut PathSimple) { diff --git a/src/lib.rs b/src/lib.rs index bd59686d2d..707cbf6ade 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,11 +83,13 @@ mod op; pub use op::{BinOp, UnOp}; mod ty; -pub use ty::{Abi, AbiKind, AngleBracketedParameterData, BareFnArg, BareFnArgName, BareFnType, - ReturnType, MutType, Mutability, ParenthesizedParameterData, Path, - PathParameters, PathSegment, PolyTraitRef, QSelf, Type, TypeBinding, Unsafety, - TypeSlice, TypeArray, TypePtr, TypeReference, TypeBareFn, TypeNever, TypeTup, TypePath, - TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, TypeGroup, GenericArg}; +pub use ty::{Abi, AbiKind, AngleBracketedGenericArguments, BareFnArg, + BareFnArgName, BareFnType, ReturnType, MutType, Mutability, + ParenthesizedGenericArguments, Path, PathArguments, PathSegment, + PolyTraitRef, QSelf, Type, TypeBinding, Unsafety, TypeSlice, + TypeArray, TypePtr, TypeReference, TypeBareFn, TypeNever, TypeTup, + TypePath, TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, + TypeGroup, GenericArgument}; #[cfg(feature = "printing")] pub use ty::PathTokens; diff --git a/src/ty.rs b/src/ty.rs index 77a43fb9f0..413fe5b8c8 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -45,7 +45,7 @@ ast_enum_of_structs! { /// A path (`module::module::...::Type`), optionally /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// - /// Type parameters are stored in the Path itself + /// Type arguments are stored in the Path itself pub Path(TypePath { pub qself: Option, pub path: Path, @@ -141,12 +141,12 @@ ast_struct! { pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, - /// Type/lifetime parameters attached to this path. They come in + /// Type/lifetime arguments attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. Note that /// this is more than just simple syntactic sugar; the use of /// parens affects the region binding rules, so we preserve the /// distinction. - pub parameters: PathParameters, + pub arguments: PathArguments, } } @@ -156,43 +156,43 @@ impl From for PathSegment fn from(ident: T) -> Self { PathSegment { ident: ident.into(), - parameters: PathParameters::None, + arguments: PathArguments::None, } } } ast_enum! { - /// Parameters of a path segment. + /// Arguments of a path segment. /// /// E.g. `` as in `Foo` or `(A, B)` as in `Foo(A, B)` - pub enum PathParameters { + pub enum PathArguments { None, /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>` - AngleBracketed(AngleBracketedParameterData), + AngleBracketed(AngleBracketedGenericArguments), /// The `(A, B)` and `C` in `Foo(A, B) -> C` - Parenthesized(ParenthesizedParameterData), + Parenthesized(ParenthesizedGenericArguments), } } -impl Default for PathParameters { +impl Default for PathArguments { fn default() -> Self { - PathParameters::None + PathArguments::None } } -impl PathParameters { +impl PathArguments { pub fn is_empty(&self) -> bool { match *self { - PathParameters::None => true, - PathParameters::AngleBracketed(ref bracketed) => bracketed.args.is_empty(), - PathParameters::Parenthesized(_) => false, + PathArguments::None => true, + PathArguments::AngleBracketed(ref bracketed) => bracketed.args.is_empty(), + PathArguments::Parenthesized(_) => false, } } } ast_enum! { /// A individual generic argument, like `'a`, `T`, or `Item=T`. - pub enum GenericArg { + pub enum GenericArgument { /// The lifetime parameters for this path segment. Lifetime(Lifetime), /// The type parameters for this path segment, if present. @@ -206,10 +206,10 @@ ast_enum! { ast_struct! { /// A path like `Foo<'a, T>` - pub struct AngleBracketedParameterData { + pub struct AngleBracketedGenericArguments { pub turbofish: Option, pub lt_token: Token![<], - pub args: Delimited, + pub args: Delimited, pub gt_token: Token![>], } } @@ -226,7 +226,7 @@ ast_struct! { ast_struct! { /// A path like `Foo(A,B) -> C` - pub struct ParenthesizedParameterData { + pub struct ParenthesizedGenericArguments { pub paren_token: tokens::Paren, /// `(A, B)` pub inputs: Delimited, @@ -515,8 +515,8 @@ pub mod parsing { named!(ty_path(allow_plus: bool) -> Type, do_parse!( qpath: qpath >> parenthesized: cond!( - qpath.1.segments.get(qpath.1.segments.len() - 1).item().parameters.is_empty(), - option!(syn!(ParenthesizedParameterData)) + qpath.1.segments.get(qpath.1.segments.len() - 1).item().arguments.is_empty(), + option!(syn!(ParenthesizedGenericArguments)) ) >> // Only allow parsing additional bounds if allow_plus is true. bounds: alt!( @@ -530,9 +530,9 @@ pub mod parsing { ({ let (qself, mut path) = qpath; if let Some(Some(parenthesized)) = parenthesized { - let parenthesized = PathParameters::Parenthesized(parenthesized); + let parenthesized = PathArguments::Parenthesized(parenthesized); let len = path.segments.len(); - path.segments.get_mut(len - 1).item_mut().parameters = parenthesized; + path.segments.get_mut(len - 1).item_mut().arguments = parenthesized; } if bounds.is_empty() { TypePath { qself: qself, path: path }.into() @@ -600,11 +600,11 @@ pub mod parsing { map!(keyword!(self), |s| (None, s.into())) )); - impl Synom for ParenthesizedParameterData { + impl Synom for ParenthesizedGenericArguments { named!(parse -> Self, do_parse!( data: parens!(call!(Delimited::parse_terminated)) >> output: syn!(ReturnType) >> - (ParenthesizedParameterData { + (ParenthesizedGenericArguments { paren_token: data.1, inputs: data.0, output: output, @@ -691,23 +691,23 @@ pub mod parsing { } } - impl Synom for GenericArg { + impl Synom for GenericArgument { named!(parse -> Self, alt!( - call!(ty_no_eq_after) => { GenericArg::Type } + call!(ty_no_eq_after) => { GenericArgument::Type } | - syn!(Lifetime) => { GenericArg::Lifetime } + syn!(Lifetime) => { GenericArgument::Lifetime } | - syn!(TypeBinding) => { GenericArg::TypeBinding } + syn!(TypeBinding) => { GenericArgument::TypeBinding } )); } - impl Synom for AngleBracketedParameterData { + impl Synom for AngleBracketedGenericArguments { named!(parse -> Self, do_parse!( turbofish: option!(punct!(::)) >> lt: punct!(<) >> args: call!(Delimited::parse_terminated) >> gt: punct!(>) >> - (AngleBracketedParameterData { + (AngleBracketedGenericArguments { turbofish: turbofish, lt_token: lt, args: args, @@ -720,10 +720,10 @@ pub mod parsing { named!(parse -> Self, alt!( do_parse!( ident: syn!(Ident) >> - parameters: syn!(AngleBracketedParameterData) >> + arguments: syn!(AngleBracketedGenericArguments) >> (PathSegment { ident: ident, - parameters: PathParameters::AngleBracketed(parameters), + arguments: PathArguments::AngleBracketed(arguments), }) ) | @@ -775,15 +775,15 @@ pub mod parsing { bound_lifetimes: option!(syn!(BoundLifetimes)) >> trait_ref: syn!(Path) >> parenthesized: option!(cond_reduce!( - trait_ref.segments.get(trait_ref.segments.len() - 1).item().parameters.is_empty(), - syn!(ParenthesizedParameterData) + trait_ref.segments.get(trait_ref.segments.len() - 1).item().arguments.is_empty(), + syn!(ParenthesizedGenericArguments) )) >> ({ let mut trait_ref = trait_ref; if let Some(parenthesized) = parenthesized { - let parenthesized = PathParameters::Parenthesized(parenthesized); + let parenthesized = PathArguments::Parenthesized(parenthesized); let len = trait_ref.segments.len(); - trait_ref.segments.get_mut(len - 1).item_mut().parameters = parenthesized; + trait_ref.segments.get_mut(len - 1).item_mut().arguments = parenthesized; } PolyTraitRef { bound_lifetimes: bound_lifetimes, @@ -1005,35 +1005,35 @@ mod printing { impl ToTokens for PathSegment { fn to_tokens(&self, tokens: &mut Tokens) { self.ident.to_tokens(tokens); - self.parameters.to_tokens(tokens); + self.arguments.to_tokens(tokens); } } - impl ToTokens for PathParameters { + impl ToTokens for PathArguments { fn to_tokens(&self, tokens: &mut Tokens) { match *self { - PathParameters::None => {} - PathParameters::AngleBracketed(ref parameters) => { - parameters.to_tokens(tokens); + PathArguments::None => {} + PathArguments::AngleBracketed(ref arguments) => { + arguments.to_tokens(tokens); } - PathParameters::Parenthesized(ref parameters) => { - parameters.to_tokens(tokens); + PathArguments::Parenthesized(ref arguments) => { + arguments.to_tokens(tokens); } } } } - impl ToTokens for GenericArg { + impl ToTokens for GenericArgument { fn to_tokens(&self, tokens: &mut Tokens) { match *self { - GenericArg::Lifetime(ref lt) => lt.to_tokens(tokens), - GenericArg::Type(ref ty) => ty.to_tokens(tokens), - GenericArg::TypeBinding(ref tb) => tb.to_tokens(tokens), + GenericArgument::Lifetime(ref lt) => lt.to_tokens(tokens), + GenericArgument::Type(ref ty) => ty.to_tokens(tokens), + GenericArgument::TypeBinding(ref tb) => tb.to_tokens(tokens), } } } - impl ToTokens for AngleBracketedParameterData { + impl ToTokens for AngleBracketedGenericArguments { fn to_tokens(&self, tokens: &mut Tokens) { self.turbofish.to_tokens(tokens); self.lt_token.to_tokens(tokens); @@ -1050,7 +1050,7 @@ mod printing { } } - impl ToTokens for ParenthesizedParameterData { + impl ToTokens for ParenthesizedGenericArguments { fn to_tokens(&self, tokens: &mut Tokens) { self.paren_token.surround(tokens, |tokens| { self.inputs.to_tokens(tokens); diff --git a/syn_codegen/src/main.rs b/syn_codegen/src/main.rs index a1757d29f9..2a60844bf7 100644 --- a/syn_codegen/src/main.rs +++ b/syn_codegen/src/main.rs @@ -308,15 +308,15 @@ mod codegen { Fold, } - fn first_param(params: &PathParameters) -> &Type { + fn first_arg(params: &PathArguments) -> &Type { let data = match *params { - PathParameters::AngleBracketed(ref data) => data, - _ => panic!("Expected at least 1 type parameter here"), + PathArguments::AngleBracketed(ref data) => data, + _ => panic!("Expected at least 1 type argument here"), }; - match *data.args.first().expect("Expected at least 1 type parameter here").item() { - &GenericArg::Type(ref ty) => ty, - _ => panic!("Expected at least 1 type parmeter here"), + match *data.args.first().expect("Expected at least 1 type argument here").item() { + &GenericArgument::Type(ref ty) => ty, + _ => panic!("Expected at least 1 type argument here"), } } @@ -363,7 +363,7 @@ mod codegen { } if seg.ident == "Box" { - let ty = first_param(&seg.parameters); + let ty = first_arg(&seg.arguments); if let Some(seg) = last_segment(ty) { if kind == Kind::Fold { let name = quote!(*#name); @@ -398,7 +398,7 @@ mod codegen { if seg.ident == "Vec" || seg.ident == "Delimited" { let is_vec = seg.ident == "Vec"; - let ty = first_param(&seg.parameters); + let ty = first_arg(&seg.arguments); if let Some(seg) = last_segment(ty) { if let Some(val) = box_visit(seg, lookup, kind, "e!(it), eos_full) { return Some(match kind { @@ -465,7 +465,7 @@ mod codegen { } if seg.ident == "Option" { - let ty = first_param(&seg.parameters); + let ty = first_arg(&seg.arguments); if let Some(seg) = last_segment(ty) { let it = match kind { Kind::Fold => quote!(it), diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs index c56d59a99b..a65472eaa6 100644 --- a/tests/test_derive_input.rs +++ b/tests/test_derive_input.rs @@ -114,12 +114,12 @@ fn test_struct() { segments: vec![ PathSegment { ident: "Vec".into(), - parameters: PathParameters::AngleBracketed( - AngleBracketedParameterData { + arguments: PathArguments::AngleBracketed( + AngleBracketedGenericArguments { turbofish: None, lt_token: Default::default(), args: vec![ - GenericArg::Type(Type::from(TypePath { + GenericArgument::Type(Type::from(TypePath { qself: None, path: "Attribute".into(), })), From c680e61aec7ad104441ec8dd6fc8c122c9dcacde Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 19:07:20 -0500 Subject: [PATCH 6/8] Add support for parsing const expressions in type argument position --- src/gen/fold.rs | 5 +++++ src/gen/visit.rs | 3 +++ src/gen/visit_mut.rs | 3 +++ src/ty.rs | 23 +++++++++++++++++++++++ 4 files changed, 34 insertions(+) diff --git a/src/gen/fold.rs b/src/gen/fold.rs index 6a6dddcab3..186e38028c 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -1470,6 +1470,11 @@ pub fn fold_generic_argument(_visitor: &mut V, _i: GenericAr _visitor.fold_type_binding(_binding_0), ) } + Const(_binding_0, ) => { + Const ( + full!(_visitor.fold_expr_block(_binding_0)), + ) + } } } diff --git a/src/gen/visit.rs b/src/gen/visit.rs index efe7b47487..3387d992d7 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -1143,6 +1143,9 @@ pub fn visit_generic_argument<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, TypeBinding(ref _binding_0, ) => { _visitor.visit_type_binding(&* _binding_0); } + Const(ref _binding_0, ) => { + full!(_visitor.visit_expr_block(&* _binding_0)); + } } } diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 77eaaca44e..aadef50cc1 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -1143,6 +1143,9 @@ pub fn visit_generic_argument_mut(_visitor: &mut V, _i: TypeBinding(ref mut _binding_0, ) => { _visitor.visit_type_binding_mut(&mut * _binding_0); } + Const(ref mut _binding_0, ) => { + full!(_visitor.visit_expr_block_mut(&mut * _binding_0)); + } } } diff --git a/src/ty.rs b/src/ty.rs index 413fe5b8c8..085bf9cd4c 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -201,6 +201,11 @@ ast_enum! { /// /// E.g., `Foo`. TypeBinding(TypeBinding), + /// Const expression. Must be inside of a block. + /// + /// NOTE: Identity expressions are represented as Type arguments, as + /// they are indistinguishable syntactically. + Const(ExprBlock), } } @@ -691,6 +696,18 @@ pub mod parsing { } } + #[cfg(not(feature = "full"))] + impl Synom for GenericArgument { + named!(parse -> Self, alt!( + call!(ty_no_eq_after) => { GenericArgument::Type } + | + syn!(Lifetime) => { GenericArgument::Lifetime } + | + syn!(TypeBinding) => { GenericArgument::TypeBinding } + )); + } + + #[cfg(feature = "full")] impl Synom for GenericArgument { named!(parse -> Self, alt!( call!(ty_no_eq_after) => { GenericArgument::Type } @@ -698,6 +715,8 @@ pub mod parsing { syn!(Lifetime) => { GenericArgument::Lifetime } | syn!(TypeBinding) => { GenericArgument::TypeBinding } + | + syn!(ExprBlock) => { GenericArgument::Const } )); } @@ -1029,6 +1048,10 @@ mod printing { GenericArgument::Lifetime(ref lt) => lt.to_tokens(tokens), GenericArgument::Type(ref ty) => ty.to_tokens(tokens), GenericArgument::TypeBinding(ref tb) => tb.to_tokens(tokens), + #[cfg(not(feature = "full"))] + GenericArgument::Const(_) => unreachable!(), + #[cfg(feature = "full")] + GenericArgument::Const(ref eb) => eb.to_tokens(tokens), } } } From f1fdc0b7e1896277ee7e613ef138226cc7130679 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Dec 2017 19:58:32 -0500 Subject: [PATCH 7/8] Add support for parsing const parameters --- src/gen/fold.rs | 19 +++++++++++++++ src/gen/visit.rs | 15 ++++++++++++ src/gen/visit_mut.rs | 15 ++++++++++++ src/generics.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 5 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/gen/fold.rs b/src/gen/fold.rs index 186e38028c..ed7db7c93d 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -97,6 +97,8 @@ fn fold_body_struct(&mut self, i: BodyStruct) -> BodyStruct { fold_body_struct(s fn fold_bound_lifetimes(&mut self, i: BoundLifetimes) -> BoundLifetimes { fold_bound_lifetimes(self, i) } # [ cfg ( feature = "full" ) ] fn fold_capture_by(&mut self, i: CaptureBy) -> CaptureBy { fold_capture_by(self, i) } + +fn fold_const_param(&mut self, i: ConstParam) -> ConstParam { fold_const_param(self, i) } # [ cfg ( feature = "full" ) ] fn fold_constness(&mut self, i: Constness) -> Constness { fold_constness(self, i) } # [ cfg ( feature = "full" ) ] @@ -752,6 +754,18 @@ pub fn fold_capture_by(_visitor: &mut V, _i: CaptureBy) -> C Ref => { Ref } } } + +pub fn fold_const_param(_visitor: &mut V, _i: ConstParam) -> ConstParam { + ConstParam { + attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }), + const_token: _i . const_token, + ident: _i . ident, + colon_token: _i . colon_token, + ty: _visitor.fold_type(_i . ty), + eq_token: _i . eq_token, + default: (_i . default).map(|it| { _visitor.fold_expr(it) }), + } +} # [ cfg ( feature = "full" ) ] pub fn fold_constness(_visitor: &mut V, _i: Constness) -> Constness { use ::Constness::*; @@ -1491,6 +1505,11 @@ pub fn fold_generic_param(_visitor: &mut V, _i: GenericParam _visitor.fold_type_param(_binding_0), ) } + Const(_binding_0, ) => { + Const ( + _visitor.fold_const_param(_binding_0), + ) + } } } diff --git a/src/gen/visit.rs b/src/gen/visit.rs index 3387d992d7..b91254f545 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -70,6 +70,8 @@ fn visit_body_struct(&mut self, i: &'ast BodyStruct) { visit_body_struct(self, i fn visit_bound_lifetimes(&mut self, i: &'ast BoundLifetimes) { visit_bound_lifetimes(self, i) } # [ cfg ( feature = "full" ) ] fn visit_capture_by(&mut self, i: &'ast CaptureBy) { visit_capture_by(self, i) } + +fn visit_const_param(&mut self, i: &'ast ConstParam) { visit_const_param(self, i) } # [ cfg ( feature = "full" ) ] fn visit_constness(&mut self, i: &'ast Constness) { visit_constness(self, i) } # [ cfg ( feature = "full" ) ] @@ -625,6 +627,16 @@ pub fn visit_capture_by<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: & Ref => { } } } + +pub fn visit_const_param<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ConstParam) { + for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) }; + // Skipped field _i . const_token; + // Skipped field _i . ident; + // Skipped field _i . colon_token; + _visitor.visit_type(&_i . ty); + // Skipped field _i . eq_token; + if let Some(ref it) = _i . default { _visitor.visit_expr(&* it) }; +} # [ cfg ( feature = "full" ) ] pub fn visit_constness<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Constness) { use ::Constness::*; @@ -1158,6 +1170,9 @@ pub fn visit_generic_param<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i Type(ref _binding_0, ) => { _visitor.visit_type_param(&* _binding_0); } + Const(ref _binding_0, ) => { + _visitor.visit_const_param(&* _binding_0); + } } } diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index aadef50cc1..5ff8dce5a1 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -70,6 +70,8 @@ fn visit_body_struct_mut(&mut self, i: &mut BodyStruct) { visit_body_struct_mut( fn visit_bound_lifetimes_mut(&mut self, i: &mut BoundLifetimes) { visit_bound_lifetimes_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_capture_by_mut(&mut self, i: &mut CaptureBy) { visit_capture_by_mut(self, i) } + +fn visit_const_param_mut(&mut self, i: &mut ConstParam) { visit_const_param_mut(self, i) } # [ cfg ( feature = "full" ) ] fn visit_constness_mut(&mut self, i: &mut Constness) { visit_constness_mut(self, i) } # [ cfg ( feature = "full" ) ] @@ -625,6 +627,16 @@ pub fn visit_capture_by_mut(_visitor: &mut V, _i: &mut C Ref => { } } } + +pub fn visit_const_param_mut(_visitor: &mut V, _i: &mut ConstParam) { + for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute_mut(&mut it) }; + // Skipped field _i . const_token; + // Skipped field _i . ident; + // Skipped field _i . colon_token; + _visitor.visit_type_mut(&mut _i . ty); + // Skipped field _i . eq_token; + if let Some(ref mut it) = _i . default { _visitor.visit_expr_mut(&mut * it) }; +} # [ cfg ( feature = "full" ) ] pub fn visit_constness_mut(_visitor: &mut V, _i: &mut Constness) { use ::Constness::*; @@ -1158,6 +1170,9 @@ pub fn visit_generic_param_mut(_visitor: &mut V, _i: &mu Type(ref mut _binding_0, ) => { _visitor.visit_type_param_mut(&mut * _binding_0); } + Const(ref mut _binding_0, ) => { + _visitor.visit_const_param_mut(&mut * _binding_0); + } } } diff --git a/src/generics.rs b/src/generics.rs index f9fa655265..d3c1ac0837 100644 --- a/src/generics.rs +++ b/src/generics.rs @@ -31,6 +31,16 @@ ast_enum_of_structs! { pub eq_token: Option, pub default: Option, }), + /// A generic const parameter, e.g. `const LENGTH: usize`. + pub Const(ConstParam { + pub attrs: Vec, + pub const_token: Token![const], + pub ident: Ident, + pub colon_token: Token![:], + pub ty: Type, + pub eq_token: Option, + pub default: Option, + }), } } @@ -305,6 +315,26 @@ pub mod parsing { } } + impl Synom for ConstParam { + named!(parse -> Self, do_parse!( + attrs: many0!(call!(Attribute::parse_outer)) >> + const_: keyword!(const) >> + ident: syn!(Ident) >> + colon: punct!(:) >> + ty: syn!(Type) >> + eq_def: option!(tuple!(punct!(=), syn!(Expr))) >> + (ConstParam { + attrs: attrs, + const_token: const_, + ident: ident, + colon_token: colon, + ty: ty, + eq_token: eq_def.as_ref().map(|&(eq, _)| eq), + default: eq_def.map(|(_, def)| def), + }) + )); + } + impl Synom for WhereClause { named!(parse -> Self, alt!( do_parse!( @@ -400,6 +430,14 @@ mod printing { param.bounds.to_tokens(tokens); } } + GenericParam::Const(ref param) => { + // Leave off the const parameter defaults + tokens.append_all(param.attrs.outer()); + param.const_token.to_tokens(tokens); + param.ident.to_tokens(tokens); + param.colon_token.to_tokens(tokens); + param.ty.to_tokens(tokens); + } } param.delimiter().to_tokens(tokens); } @@ -424,6 +462,10 @@ mod printing { // Leave off the type parameter defaults param.ident.to_tokens(tokens); } + GenericParam::Const(ref param) => { + // Leave off the const parameter defaults + param.ident.to_tokens(tokens); + } } param.delimiter().to_tokens(tokens); } @@ -496,6 +538,20 @@ mod printing { } } + impl ToTokens for ConstParam { + fn to_tokens(&self, tokens: &mut Tokens) { + tokens.append_all(self.attrs.outer()); + self.const_token.to_tokens(tokens); + self.ident.to_tokens(tokens); + self.colon_token.to_tokens(tokens); + self.ty.to_tokens(tokens); + if self.default.is_some() { + self.eq_token.unwrap_or(Default::default()).to_tokens(tokens); + self.default.to_tokens(tokens); + } + } + } + impl ToTokens for WhereClause { fn to_tokens(&self, tokens: &mut Tokens) { if !self.predicates.is_empty() { diff --git a/src/lib.rs b/src/lib.rs index 707cbf6ade..92f3386348 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ pub use expr::{Arm, BindingMode, Block, CaptureBy, FieldPat, FieldValue, Local, mod generics; pub use generics::{Generics, GenericParam, LifetimeDef, TraitBoundModifier, TypeParam, TypeParamBound, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate, - WhereRegionPredicate, BoundLifetimes}; + WhereRegionPredicate, BoundLifetimes, ConstParam}; #[cfg(feature = "printing")] pub use generics::{ImplGenerics, Turbofish, TypeGenerics}; From 78ee520d580bbd4ab3f190ef5dd4ea853b629d04 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 4 Dec 2017 22:17:54 -0800 Subject: [PATCH 8/8] Fix ConstParam when building without clone-impls --- src/generics.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/generics.rs b/src/generics.rs index d3c1ac0837..9b217203db 100644 --- a/src/generics.rs +++ b/src/generics.rs @@ -323,14 +323,20 @@ pub mod parsing { colon: punct!(:) >> ty: syn!(Type) >> eq_def: option!(tuple!(punct!(=), syn!(Expr))) >> - (ConstParam { - attrs: attrs, - const_token: const_, - ident: ident, - colon_token: colon, - ty: ty, - eq_token: eq_def.as_ref().map(|&(eq, _)| eq), - default: eq_def.map(|(_, def)| def), + ({ + let (eq_token, default) = match eq_def { + Some((eq_token, default)) => (Some(eq_token), Some(default)), + None => (None, None), + }; + ConstParam { + attrs: attrs, + const_token: const_, + ident: ident, + colon_token: colon, + ty: ty, + eq_token: eq_token, + default: default, + } }) )); } @@ -546,7 +552,7 @@ mod printing { self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); if self.default.is_some() { - self.eq_token.unwrap_or(Default::default()).to_tokens(tokens); + TokensOrDefault(&self.eq_token).to_tokens(tokens); self.default.to_tokens(tokens); } }