#! [allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]
#[ macro_use]
mod macros;
use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use syn::{Item, ItemTrait};
#[ test]
fn test_macro_variable_attr() {
// mimics the token stream corresponding to `$attr fn f() {}`
let tokens = TokenStream::from_iter([
TokenTree::Group(Group::new(Delimiter::None, quote! { #[ test] })),
TokenTree::Ident(Ident::new("fn" , Span::call_site())),
TokenTree::Ident(Ident::new("f" , Span::call_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
]);
snapshot!(tokens as Item, @r#"
Item::Fn {
attrs: [
Attribute {
style: AttrStyle::Outer,
meta: Meta::Path {
segments: [
PathSegment {
ident: "test" ,
},
],
},
},
],
vis: Visibility::Inherited,
sig: Signature {
ident: "f" ,
generics: Generics,
output: ReturnType::Default,
},
block: Block {
stmts: [],
},
}
"#);
}
#[ test]
fn test_negative_impl() {
// Rustc parses all of the following.
#[ cfg(any())]
impl ! {}
let tokens = quote! {
impl ! {}
};
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics,
self_ty: Type ::Never,
}
"#);
#[ cfg(any())]
#[ rustfmt::skip]
impl !Trait {}
let tokens = quote! {
impl !Trait {}
};
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics,
self_ty: Type ::Verbatim(`! Trait `),
}
"#);
#[ cfg(any())]
impl !Trait for T {}
let tokens = quote! {
impl !Trait for T {}
};
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics,
trait_: Some((
Some,
Path {
segments: [
PathSegment {
ident: "Trait" ,
},
],
},
)),
self_ty: Type ::Path {
path: Path {
segments: [
PathSegment {
ident: "T" ,
},
],
},
},
}
"#);
#[ cfg(any())]
#[ rustfmt::skip]
impl !! {}
let tokens = quote! {
impl !! {}
};
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics,
self_ty: Type ::Verbatim(`! !`),
}
"#);
}
#[ test]
fn test_macro_variable_impl() {
// mimics the token stream corresponding to `impl $trait for $ty {}`
let tokens = TokenStream::from_iter([
TokenTree::Ident(Ident::new("impl" , Span::call_site())),
TokenTree::Group(Group::new(Delimiter::None, quote!(Trait ))),
TokenTree::Ident(Ident::new("for" , Span::call_site())),
TokenTree::Group(Group::new(Delimiter::None, quote!(Type ))),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
]);
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics,
trait_: Some((
None,
Path {
segments: [
PathSegment {
ident: "Trait" ,
},
],
},
)),
self_ty: Type ::Group {
elem: Type ::Path {
path: Path {
segments: [
PathSegment {
ident: "Type" ,
},
],
},
},
},
}
"#);
}
#[ test]
fn test_supertraits() {
// Rustc parses all of the following.
#[ rustfmt::skip]
let tokens = quote!(trait Trait where {});
snapshot!(tokens as ItemTrait, @r#"
ItemTrait {
vis: Visibility::Inherited,
ident: "Trait" ,
generics: Generics {
where_clause: Some(WhereClause),
},
}
"#);
#[ rustfmt::skip]
let tokens = quote!(trait Trait : where {});
snapshot!(tokens as ItemTrait, @r#"
ItemTrait {
vis: Visibility::Inherited,
ident: "Trait" ,
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
}
"#);
#[ rustfmt::skip]
let tokens = quote!(trait Trait : Sized where {});
snapshot!(tokens as ItemTrait, @r#"
ItemTrait {
vis: Visibility::Inherited,
ident: "Trait" ,
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
supertraits: [
TypeParamBound::Trait (TraitBound {
path: Path {
segments: [
PathSegment {
ident: "Sized" ,
},
],
},
}),
],
}
"#);
#[ rustfmt::skip]
let tokens = quote!(trait Trait : Sized + where {});
snapshot!(tokens as ItemTrait, @r#"
ItemTrait {
vis: Visibility::Inherited,
ident: "Trait" ,
generics: Generics {
where_clause: Some(WhereClause),
},
colon_token: Some,
supertraits: [
TypeParamBound::Trait (TraitBound {
path: Path {
segments: [
PathSegment {
ident: "Sized" ,
},
],
},
}),
Token![+],
],
}
"#);
}
#[ test]
fn test_type_empty_bounds() {
#[ rustfmt::skip]
let tokens = quote! {
trait Foo {
type Bar: ;
}
};
snapshot!(tokens as ItemTrait, @r#"
ItemTrait {
vis: Visibility::Inherited,
ident: "Foo" ,
generics: Generics,
items: [
TraitItem::Type {
ident: "Bar" ,
generics: Generics,
colon_token: Some,
},
],
}
"#);
}
#[ test]
fn test_impl_visibility() {
let tokens = quote! {
pub default unsafe impl union {}
};
snapshot!(tokens as Item, @"Item::Verbatim(`pub default unsafe impl union { }`)" );
}
#[ test]
fn test_impl_type_parameter_defaults() {
#[ cfg(any())]
impl <T = ()> () {}
let tokens = quote! {
impl <T = ()> () {}
};
snapshot!(tokens as Item, @r#"
Item::Impl {
generics: Generics {
lt_token: Some,
params: [
GenericParam::Type (TypeParam {
ident: "T" ,
eq_token: Some,
default: Some(Type ::Tuple),
}),
],
gt_token: Some,
},
self_ty: Type ::Tuple,
}
"#);
}
#[ test]
fn test_impl_trait_trailing_plus() {
let tokens = quote! {
fn f() -> impl Sized + {}
};
snapshot!(tokens as Item, @r#"
Item::Fn {
vis: Visibility::Inherited,
sig: Signature {
ident: "f" ,
generics: Generics,
output: ReturnType::Type (
Type ::ImplTrait {
bounds: [
TypeParamBound::Trait (TraitBound {
path: Path {
segments: [
PathSegment {
ident: "Sized" ,
},
],
},
}),
Token![+],
],
},
),
},
block: Block {
stmts: [],
},
}
"#);
}
Messung V0.5 in Prozent C=96 H=99 G=97
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland