Files
Android11/external/rust/crates/syn/0.15.42/tests/test_generics.rs
2023-10-13 14:01:41 +00:00

289 lines
9.4 KiB
Rust

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);
}