chore(vendor): add anyhow crate
This commit was merged in pull request #68.
This commit is contained in:
363
third_party/crates/syn-3.0.6/tests/test_generics.rs
vendored
Normal file
363
third_party/crates/syn-3.0.6/tests/test_generics.rs
vendored
Normal file
@@ -0,0 +1,363 @@
|
||||
#![allow(
|
||||
clippy::elidable_lifetime_names,
|
||||
clippy::manual_let_else,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::too_many_lines,
|
||||
clippy::uninlined_format_args
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
mod snapshot;
|
||||
|
||||
mod debug;
|
||||
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse_quote, DeriveInput, GenericParam, Generics, ItemFn, Lifetime, LifetimeParam,
|
||||
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",
|
||||
},
|
||||
],
|
||||
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 {
|
||||
modifiers: TraitBoundModifiers,
|
||||
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_type_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 {
|
||||
modifiers: TraitBoundModifiers,
|
||||
path: Path {
|
||||
segments: [
|
||||
PathSegment {
|
||||
ident: "Debug",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
"#);
|
||||
|
||||
let tokens = quote!(?Sized);
|
||||
snapshot!(tokens as TypeParamBound, @r#"
|
||||
TypeParamBound::Trait(TraitBound {
|
||||
modifiers: TraitBoundModifiers,
|
||||
maybe: Some,
|
||||
path: Path {
|
||||
segments: [
|
||||
PathSegment {
|
||||
ident: "Sized",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
"#);
|
||||
|
||||
let tokens = quote!(for<'a> Trait);
|
||||
snapshot!(tokens as TypeParamBound, @r#"
|
||||
TypeParamBound::Trait(TraitBound {
|
||||
lifetimes: Some(BoundLifetimes {
|
||||
lifetimes: [
|
||||
GenericParam::Lifetime(LifetimeParam {
|
||||
lifetime: Lifetime {
|
||||
ident: "a",
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
modifiers: TraitBoundModifiers,
|
||||
path: Path {
|
||||
segments: [
|
||||
PathSegment {
|
||||
ident: "Trait",
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
"#);
|
||||
|
||||
let tokens = quote!(for<> ?Trait);
|
||||
let err = syn::parse2::<TypeParamBound>(tokens).unwrap_err();
|
||||
assert_eq!(
|
||||
"`for<...>` binder not allowed with `?` trait polarity modifier",
|
||||
err.to_string(),
|
||||
);
|
||||
|
||||
let tokens = quote!(?for<> Trait);
|
||||
let err = syn::parse2::<TypeParamBound>(tokens).unwrap_err();
|
||||
assert_eq!(
|
||||
"`for<...>` binder not allowed with `?` trait polarity modifier",
|
||||
err.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
#[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,
|
||||
modifiers: FnModifiers,
|
||||
sig: Signature {
|
||||
safety: Safety::Default,
|
||||
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 {
|
||||
modifiers: TraitBoundModifiers,
|
||||
path: Path {
|
||||
segments: [
|
||||
PathSegment {
|
||||
ident: "FnOnce",
|
||||
arguments: PathArguments::Parenthesized {
|
||||
output: ReturnType::Type(
|
||||
Type::Path {
|
||||
path: Path {
|
||||
segments: [
|
||||
PathSegment {
|
||||
ident: "i32",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
Token![+],
|
||||
TypeParamBound::Trait(TraitBound {
|
||||
modifiers: TraitBoundModifiers,
|
||||
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);
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/dtolnay/syn/issues/1718
|
||||
#[test]
|
||||
#[allow(clippy::map_unwrap_or)]
|
||||
fn no_opaque_drop() {
|
||||
let mut generics = Generics::default();
|
||||
|
||||
let _ = generics
|
||||
.lifetimes()
|
||||
.next()
|
||||
.map(|param| param.lifetime.clone())
|
||||
.unwrap_or_else(|| {
|
||||
let lifetime: Lifetime = parse_quote!('a);
|
||||
generics.params.insert(
|
||||
0,
|
||||
GenericParam::Lifetime(LifetimeParam::new(lifetime.clone())),
|
||||
);
|
||||
lifetime
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_param_with_colon_and_no_bounds() {
|
||||
let tokens = quote!(T:);
|
||||
snapshot!(tokens as GenericParam, @r#"
|
||||
GenericParam::Type(TypeParam {
|
||||
ident: "T",
|
||||
colon_token: Some,
|
||||
})
|
||||
"#);
|
||||
}
|
||||
Reference in New Issue
Block a user