diff options
Diffstat (limited to 'rust/vendor/syn-0.15.44/tests/test_generics.rs')
-rw-r--r-- | rust/vendor/syn-0.15.44/tests/test_generics.rs | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/rust/vendor/syn-0.15.44/tests/test_generics.rs b/rust/vendor/syn-0.15.44/tests/test_generics.rs new file mode 100644 index 0000000..27b204e --- /dev/null +++ b/rust/vendor/syn-0.15.44/tests/test_generics.rs @@ -0,0 +1,288 @@ +extern crate quote; +extern crate syn; + +mod features; + +#[macro_use] +mod macros; + +use quote::quote; +use syn::{DeriveInput, ItemFn, TypeParamBound, WhereClause, WherePredicate}; + +#[test] +fn test_split_for_impl() { + let input = quote! { + struct S<'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug; + }; + + snapshot!(input as DeriveInput, @r###" + ⋮DeriveInput { + ⋮ vis: Inherited, + ⋮ ident: "S", + ⋮ generics: Generics { + ⋮ lt_token: Some, + ⋮ params: [ + ⋮ Lifetime(LifetimeDef { + ⋮ lifetime: Lifetime { + ⋮ ident: "a", + ⋮ }, + ⋮ }), + ⋮ Lifetime(LifetimeDef { + ⋮ lifetime: Lifetime { + ⋮ ident: "b", + ⋮ }, + ⋮ colon_token: Some, + ⋮ bounds: [ + ⋮ Lifetime { + ⋮ ident: "a", + ⋮ }, + ⋮ ], + ⋮ }), + ⋮ Type(TypeParam { + ⋮ attrs: [ + ⋮ Attribute { + ⋮ style: Outer, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "may_dangle", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ tts: ``, + ⋮ }, + ⋮ ], + ⋮ ident: "T", + ⋮ colon_token: Some, + ⋮ bounds: [ + ⋮ Lifetime(Lifetime { + ⋮ ident: "a", + ⋮ }), + ⋮ ], + ⋮ eq_token: Some, + ⋮ default: Some(Type::Tuple), + ⋮ }), + ⋮ ], + ⋮ gt_token: Some, + ⋮ where_clause: Some(WhereClause { + ⋮ predicates: [ + ⋮ Type(PredicateType { + ⋮ bounded_ty: Type::Path { + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "T", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }, + ⋮ bounds: [ + ⋮ Trait(TraitBound { + ⋮ modifier: None, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "Debug", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }), + ⋮ ], + ⋮ }), + ⋮ ], + ⋮ }), + ⋮ }, + ⋮ data: Data::Struct { + ⋮ fields: Unit, + ⋮ semi_token: Some, + ⋮ }, + ⋮} + "###); + + let generics = input.generics; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let generated = quote! { + impl #impl_generics MyTrait for Test #ty_generics #where_clause {} + }; + let expected = quote! { + impl<'a, 'b: 'a, #[may_dangle] T: 'a> MyTrait + for Test<'a, 'b, T> + where + T: Debug + {} + }; + assert_eq!(generated.to_string(), expected.to_string()); + + let turbofish = ty_generics.as_turbofish(); + let generated = quote! { + Test #turbofish + }; + let expected = quote! { + Test::<'a, 'b, T> + }; + assert_eq!(generated.to_string(), expected.to_string()); +} + +#[test] +fn test_ty_param_bound() { + let tokens = quote!('a); + snapshot!(tokens as TypeParamBound, @r###" + ⋮Lifetime(Lifetime { + ⋮ ident: "a", + ⋮}) + "###); + + let tokens = quote!('_); + snapshot!(tokens as TypeParamBound, @r###" + ⋮Lifetime(Lifetime { + ⋮ ident: "_", + ⋮}) + "###); + + let tokens = quote!(Debug); + snapshot!(tokens as TypeParamBound, @r###" + ⋮Trait(TraitBound { + ⋮ modifier: None, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "Debug", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮}) + "###); + + let tokens = quote!(?Sized); + snapshot!(tokens as TypeParamBound, @r###" + ⋮Trait(TraitBound { + ⋮ modifier: Maybe, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "Sized", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮}) + "###); +} + +#[test] +fn test_fn_precedence_in_where_clause() { + // This should parse as two separate bounds, `FnOnce() -> i32` and `Send` - not + // `FnOnce() -> (i32 + Send)`. + let input = quote! { + fn f<G>() + where + G: FnOnce() -> i32 + Send, + { + } + }; + + snapshot!(input as ItemFn, @r###" + ⋮ItemFn { + ⋮ vis: Inherited, + ⋮ ident: "f", + ⋮ decl: FnDecl { + ⋮ generics: Generics { + ⋮ lt_token: Some, + ⋮ params: [ + ⋮ Type(TypeParam { + ⋮ ident: "G", + ⋮ }), + ⋮ ], + ⋮ gt_token: Some, + ⋮ where_clause: Some(WhereClause { + ⋮ predicates: [ + ⋮ Type(PredicateType { + ⋮ bounded_ty: Type::Path { + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "G", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }, + ⋮ bounds: [ + ⋮ Trait(TraitBound { + ⋮ modifier: None, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "FnOnce", + ⋮ arguments: PathArguments::Parenthesized { + ⋮ output: Type( + ⋮ Type::Path { + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "i32", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }, + ⋮ ), + ⋮ }, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }), + ⋮ Trait(TraitBound { + ⋮ modifier: None, + ⋮ path: Path { + ⋮ segments: [ + ⋮ PathSegment { + ⋮ ident: "Send", + ⋮ arguments: None, + ⋮ }, + ⋮ ], + ⋮ }, + ⋮ }), + ⋮ ], + ⋮ }), + ⋮ ], + ⋮ }), + ⋮ }, + ⋮ output: Default, + ⋮ }, + ⋮ block: Block, + ⋮} + "###); + + let where_clause = input.decl.generics.where_clause.as_ref().unwrap(); + assert_eq!(where_clause.predicates.len(), 1); + + let predicate = match &where_clause.predicates[0] { + WherePredicate::Type(pred) => pred, + _ => panic!("wrong predicate kind"), + }; + + assert_eq!(predicate.bounds.len(), 2, "{:#?}", predicate.bounds); + + let first_bound = &predicate.bounds[0]; + assert_eq!(quote!(#first_bound).to_string(), "FnOnce ( ) -> i32"); + + let second_bound = &predicate.bounds[1]; + assert_eq!(quote!(#second_bound).to_string(), "Send"); +} + +#[test] +fn test_where_clause_at_end_of_input() { + let input = quote! { + where + }; + + snapshot!(input as WhereClause, @"WhereClause"); + + assert_eq!(input.predicates.len(), 0); +} |