summaryrefslogtreecommitdiff
path: root/vendor/syn/tests/test_generics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/syn/tests/test_generics.rs')
-rw-r--r--vendor/syn/tests/test_generics.rs282
1 files changed, 282 insertions, 0 deletions
diff --git a/vendor/syn/tests/test_generics.rs b/vendor/syn/tests/test_generics.rs
new file mode 100644
index 0000000..3faf0db
--- /dev/null
+++ b/vendor/syn/tests/test_generics.rs
@@ -0,0 +1,282 @@
+#![allow(
+ clippy::manual_let_else,
+ clippy::too_many_lines,
+ clippy::uninlined_format_args
+)]
+
+#[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: Visibility::Inherited,
+ ident: "S",
+ generics: Generics {
+ lt_token: Some,
+ params: [
+ GenericParam::Lifetime(LifetimeParam {
+ lifetime: Lifetime {
+ ident: "a",
+ },
+ }),
+ Token![,],
+ GenericParam::Lifetime(LifetimeParam {
+ lifetime: Lifetime {
+ ident: "b",
+ },
+ colon_token: Some,
+ bounds: [
+ Lifetime {
+ ident: "a",
+ },
+ ],
+ }),
+ Token![,],
+ GenericParam::Type(TypeParam {
+ attrs: [
+ Attribute {
+ style: AttrStyle::Outer,
+ meta: Meta::Path {
+ segments: [
+ PathSegment {
+ ident: "may_dangle",
+ },
+ ],
+ },
+ },
+ ],
+ ident: "T",
+ colon_token: Some,
+ bounds: [
+ TypeParamBound::Lifetime {
+ ident: "a",
+ },
+ ],
+ eq_token: Some,
+ default: Some(Type::Tuple),
+ }),
+ ],
+ gt_token: Some,
+ where_clause: Some(WhereClause {
+ predicates: [
+ WherePredicate::Type(PredicateType {
+ bounded_ty: Type::Path {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "T",
+ },
+ ],
+ },
+ },
+ bounds: [
+ TypeParamBound::Trait(TraitBound {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "Debug",
+ },
+ ],
+ },
+ }),
+ ],
+ }),
+ ],
+ }),
+ },
+ data: Data::Struct {
+ fields: 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###"
+ TypeParamBound::Lifetime {
+ ident: "a",
+ }
+ "###);
+
+ let tokens = quote!('_);
+ snapshot!(tokens as TypeParamBound, @r###"
+ TypeParamBound::Lifetime {
+ ident: "_",
+ }
+ "###);
+
+ let tokens = quote!(Debug);
+ snapshot!(tokens as TypeParamBound, @r###"
+ TypeParamBound::Trait(TraitBound {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "Debug",
+ },
+ ],
+ },
+ })
+ "###);
+
+ let tokens = quote!(?Sized);
+ snapshot!(tokens as TypeParamBound, @r###"
+ TypeParamBound::Trait(TraitBound {
+ modifier: TraitBoundModifier::Maybe,
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "Sized",
+ },
+ ],
+ },
+ })
+ "###);
+}
+
+#[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: Visibility::Inherited,
+ sig: Signature {
+ ident: "f",
+ generics: Generics {
+ lt_token: Some,
+ params: [
+ GenericParam::Type(TypeParam {
+ ident: "G",
+ }),
+ ],
+ gt_token: Some,
+ where_clause: Some(WhereClause {
+ predicates: [
+ WherePredicate::Type(PredicateType {
+ bounded_ty: Type::Path {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "G",
+ },
+ ],
+ },
+ },
+ bounds: [
+ TypeParamBound::Trait(TraitBound {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "FnOnce",
+ arguments: PathArguments::Parenthesized {
+ output: ReturnType::Type(
+ Type::Path {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "i32",
+ },
+ ],
+ },
+ },
+ ),
+ },
+ },
+ ],
+ },
+ }),
+ Token![+],
+ TypeParamBound::Trait(TraitBound {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "Send",
+ },
+ ],
+ },
+ }),
+ ],
+ }),
+ Token![,],
+ ],
+ }),
+ },
+ output: ReturnType::Default,
+ },
+ block: Block {
+ stmts: [],
+ },
+ }
+ "###);
+
+ let where_clause = input.sig.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);
+}