1fad3a1d3Sopenharmony_ci#![allow(clippy::uninlined_format_args)] 2fad3a1d3Sopenharmony_ci 3fad3a1d3Sopenharmony_ci#[macro_use] 4fad3a1d3Sopenharmony_cimod macros; 5fad3a1d3Sopenharmony_ci 6fad3a1d3Sopenharmony_ciuse proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; 7fad3a1d3Sopenharmony_ciuse quote::{quote, ToTokens as _}; 8fad3a1d3Sopenharmony_ciuse syn::punctuated::Punctuated; 9fad3a1d3Sopenharmony_ciuse syn::{parse_quote, token, Token, Type, TypeTuple}; 10fad3a1d3Sopenharmony_ci 11fad3a1d3Sopenharmony_ci#[test] 12fad3a1d3Sopenharmony_cifn test_mut_self() { 13fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self)").unwrap(); 14fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self,)").unwrap(); 15fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self: ())").unwrap(); 16fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self: ...)").unwrap_err(); 17fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self: mut self)").unwrap_err(); 18fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("fn(mut self::T)").unwrap_err(); 19fad3a1d3Sopenharmony_ci} 20fad3a1d3Sopenharmony_ci 21fad3a1d3Sopenharmony_ci#[test] 22fad3a1d3Sopenharmony_cifn test_macro_variable_type() { 23fad3a1d3Sopenharmony_ci // mimics the token stream corresponding to `$ty<T>` 24fad3a1d3Sopenharmony_ci let tokens = TokenStream::from_iter(vec![ 25fad3a1d3Sopenharmony_ci TokenTree::Group(Group::new(Delimiter::None, quote! { ty })), 26fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('<', Spacing::Alone)), 27fad3a1d3Sopenharmony_ci TokenTree::Ident(Ident::new("T", Span::call_site())), 28fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('>', Spacing::Alone)), 29fad3a1d3Sopenharmony_ci ]); 30fad3a1d3Sopenharmony_ci 31fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 32fad3a1d3Sopenharmony_ci Type::Path { 33fad3a1d3Sopenharmony_ci path: Path { 34fad3a1d3Sopenharmony_ci segments: [ 35fad3a1d3Sopenharmony_ci PathSegment { 36fad3a1d3Sopenharmony_ci ident: "ty", 37fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 38fad3a1d3Sopenharmony_ci args: [ 39fad3a1d3Sopenharmony_ci GenericArgument::Type(Type::Path { 40fad3a1d3Sopenharmony_ci path: Path { 41fad3a1d3Sopenharmony_ci segments: [ 42fad3a1d3Sopenharmony_ci PathSegment { 43fad3a1d3Sopenharmony_ci ident: "T", 44fad3a1d3Sopenharmony_ci }, 45fad3a1d3Sopenharmony_ci ], 46fad3a1d3Sopenharmony_ci }, 47fad3a1d3Sopenharmony_ci }), 48fad3a1d3Sopenharmony_ci ], 49fad3a1d3Sopenharmony_ci }, 50fad3a1d3Sopenharmony_ci }, 51fad3a1d3Sopenharmony_ci ], 52fad3a1d3Sopenharmony_ci }, 53fad3a1d3Sopenharmony_ci } 54fad3a1d3Sopenharmony_ci "###); 55fad3a1d3Sopenharmony_ci 56fad3a1d3Sopenharmony_ci // mimics the token stream corresponding to `$ty::<T>` 57fad3a1d3Sopenharmony_ci let tokens = TokenStream::from_iter(vec![ 58fad3a1d3Sopenharmony_ci TokenTree::Group(Group::new(Delimiter::None, quote! { ty })), 59fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Joint)), 60fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Alone)), 61fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('<', Spacing::Alone)), 62fad3a1d3Sopenharmony_ci TokenTree::Ident(Ident::new("T", Span::call_site())), 63fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('>', Spacing::Alone)), 64fad3a1d3Sopenharmony_ci ]); 65fad3a1d3Sopenharmony_ci 66fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 67fad3a1d3Sopenharmony_ci Type::Path { 68fad3a1d3Sopenharmony_ci path: Path { 69fad3a1d3Sopenharmony_ci segments: [ 70fad3a1d3Sopenharmony_ci PathSegment { 71fad3a1d3Sopenharmony_ci ident: "ty", 72fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 73fad3a1d3Sopenharmony_ci colon2_token: Some, 74fad3a1d3Sopenharmony_ci args: [ 75fad3a1d3Sopenharmony_ci GenericArgument::Type(Type::Path { 76fad3a1d3Sopenharmony_ci path: Path { 77fad3a1d3Sopenharmony_ci segments: [ 78fad3a1d3Sopenharmony_ci PathSegment { 79fad3a1d3Sopenharmony_ci ident: "T", 80fad3a1d3Sopenharmony_ci }, 81fad3a1d3Sopenharmony_ci ], 82fad3a1d3Sopenharmony_ci }, 83fad3a1d3Sopenharmony_ci }), 84fad3a1d3Sopenharmony_ci ], 85fad3a1d3Sopenharmony_ci }, 86fad3a1d3Sopenharmony_ci }, 87fad3a1d3Sopenharmony_ci ], 88fad3a1d3Sopenharmony_ci }, 89fad3a1d3Sopenharmony_ci } 90fad3a1d3Sopenharmony_ci "###); 91fad3a1d3Sopenharmony_ci} 92fad3a1d3Sopenharmony_ci 93fad3a1d3Sopenharmony_ci#[test] 94fad3a1d3Sopenharmony_cifn test_group_angle_brackets() { 95fad3a1d3Sopenharmony_ci // mimics the token stream corresponding to `Option<$ty>` 96fad3a1d3Sopenharmony_ci let tokens = TokenStream::from_iter(vec![ 97fad3a1d3Sopenharmony_ci TokenTree::Ident(Ident::new("Option", Span::call_site())), 98fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('<', Spacing::Alone)), 99fad3a1d3Sopenharmony_ci TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })), 100fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new('>', Spacing::Alone)), 101fad3a1d3Sopenharmony_ci ]); 102fad3a1d3Sopenharmony_ci 103fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 104fad3a1d3Sopenharmony_ci Type::Path { 105fad3a1d3Sopenharmony_ci path: Path { 106fad3a1d3Sopenharmony_ci segments: [ 107fad3a1d3Sopenharmony_ci PathSegment { 108fad3a1d3Sopenharmony_ci ident: "Option", 109fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 110fad3a1d3Sopenharmony_ci args: [ 111fad3a1d3Sopenharmony_ci GenericArgument::Type(Type::Group { 112fad3a1d3Sopenharmony_ci elem: Type::Path { 113fad3a1d3Sopenharmony_ci path: Path { 114fad3a1d3Sopenharmony_ci segments: [ 115fad3a1d3Sopenharmony_ci PathSegment { 116fad3a1d3Sopenharmony_ci ident: "Vec", 117fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 118fad3a1d3Sopenharmony_ci args: [ 119fad3a1d3Sopenharmony_ci GenericArgument::Type(Type::Path { 120fad3a1d3Sopenharmony_ci path: Path { 121fad3a1d3Sopenharmony_ci segments: [ 122fad3a1d3Sopenharmony_ci PathSegment { 123fad3a1d3Sopenharmony_ci ident: "u8", 124fad3a1d3Sopenharmony_ci }, 125fad3a1d3Sopenharmony_ci ], 126fad3a1d3Sopenharmony_ci }, 127fad3a1d3Sopenharmony_ci }), 128fad3a1d3Sopenharmony_ci ], 129fad3a1d3Sopenharmony_ci }, 130fad3a1d3Sopenharmony_ci }, 131fad3a1d3Sopenharmony_ci ], 132fad3a1d3Sopenharmony_ci }, 133fad3a1d3Sopenharmony_ci }, 134fad3a1d3Sopenharmony_ci }), 135fad3a1d3Sopenharmony_ci ], 136fad3a1d3Sopenharmony_ci }, 137fad3a1d3Sopenharmony_ci }, 138fad3a1d3Sopenharmony_ci ], 139fad3a1d3Sopenharmony_ci }, 140fad3a1d3Sopenharmony_ci } 141fad3a1d3Sopenharmony_ci "###); 142fad3a1d3Sopenharmony_ci} 143fad3a1d3Sopenharmony_ci 144fad3a1d3Sopenharmony_ci#[test] 145fad3a1d3Sopenharmony_cifn test_group_colons() { 146fad3a1d3Sopenharmony_ci // mimics the token stream corresponding to `$ty::Item` 147fad3a1d3Sopenharmony_ci let tokens = TokenStream::from_iter(vec![ 148fad3a1d3Sopenharmony_ci TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })), 149fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Joint)), 150fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Alone)), 151fad3a1d3Sopenharmony_ci TokenTree::Ident(Ident::new("Item", Span::call_site())), 152fad3a1d3Sopenharmony_ci ]); 153fad3a1d3Sopenharmony_ci 154fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 155fad3a1d3Sopenharmony_ci Type::Path { 156fad3a1d3Sopenharmony_ci path: Path { 157fad3a1d3Sopenharmony_ci segments: [ 158fad3a1d3Sopenharmony_ci PathSegment { 159fad3a1d3Sopenharmony_ci ident: "Vec", 160fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 161fad3a1d3Sopenharmony_ci args: [ 162fad3a1d3Sopenharmony_ci GenericArgument::Type(Type::Path { 163fad3a1d3Sopenharmony_ci path: Path { 164fad3a1d3Sopenharmony_ci segments: [ 165fad3a1d3Sopenharmony_ci PathSegment { 166fad3a1d3Sopenharmony_ci ident: "u8", 167fad3a1d3Sopenharmony_ci }, 168fad3a1d3Sopenharmony_ci ], 169fad3a1d3Sopenharmony_ci }, 170fad3a1d3Sopenharmony_ci }), 171fad3a1d3Sopenharmony_ci ], 172fad3a1d3Sopenharmony_ci }, 173fad3a1d3Sopenharmony_ci }, 174fad3a1d3Sopenharmony_ci Token![::], 175fad3a1d3Sopenharmony_ci PathSegment { 176fad3a1d3Sopenharmony_ci ident: "Item", 177fad3a1d3Sopenharmony_ci }, 178fad3a1d3Sopenharmony_ci ], 179fad3a1d3Sopenharmony_ci }, 180fad3a1d3Sopenharmony_ci } 181fad3a1d3Sopenharmony_ci "###); 182fad3a1d3Sopenharmony_ci 183fad3a1d3Sopenharmony_ci let tokens = TokenStream::from_iter(vec![ 184fad3a1d3Sopenharmony_ci TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })), 185fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Joint)), 186fad3a1d3Sopenharmony_ci TokenTree::Punct(Punct::new(':', Spacing::Alone)), 187fad3a1d3Sopenharmony_ci TokenTree::Ident(Ident::new("Element", Span::call_site())), 188fad3a1d3Sopenharmony_ci ]); 189fad3a1d3Sopenharmony_ci 190fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 191fad3a1d3Sopenharmony_ci Type::Path { 192fad3a1d3Sopenharmony_ci qself: Some(QSelf { 193fad3a1d3Sopenharmony_ci ty: Type::Slice { 194fad3a1d3Sopenharmony_ci elem: Type::Path { 195fad3a1d3Sopenharmony_ci path: Path { 196fad3a1d3Sopenharmony_ci segments: [ 197fad3a1d3Sopenharmony_ci PathSegment { 198fad3a1d3Sopenharmony_ci ident: "T", 199fad3a1d3Sopenharmony_ci }, 200fad3a1d3Sopenharmony_ci ], 201fad3a1d3Sopenharmony_ci }, 202fad3a1d3Sopenharmony_ci }, 203fad3a1d3Sopenharmony_ci }, 204fad3a1d3Sopenharmony_ci position: 0, 205fad3a1d3Sopenharmony_ci }), 206fad3a1d3Sopenharmony_ci path: Path { 207fad3a1d3Sopenharmony_ci leading_colon: Some, 208fad3a1d3Sopenharmony_ci segments: [ 209fad3a1d3Sopenharmony_ci PathSegment { 210fad3a1d3Sopenharmony_ci ident: "Element", 211fad3a1d3Sopenharmony_ci }, 212fad3a1d3Sopenharmony_ci ], 213fad3a1d3Sopenharmony_ci }, 214fad3a1d3Sopenharmony_ci } 215fad3a1d3Sopenharmony_ci "###); 216fad3a1d3Sopenharmony_ci} 217fad3a1d3Sopenharmony_ci 218fad3a1d3Sopenharmony_ci#[test] 219fad3a1d3Sopenharmony_cifn test_trait_object() { 220fad3a1d3Sopenharmony_ci let tokens = quote!(dyn for<'a> Trait<'a> + 'static); 221fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 222fad3a1d3Sopenharmony_ci Type::TraitObject { 223fad3a1d3Sopenharmony_ci dyn_token: Some, 224fad3a1d3Sopenharmony_ci bounds: [ 225fad3a1d3Sopenharmony_ci TypeParamBound::Trait(TraitBound { 226fad3a1d3Sopenharmony_ci lifetimes: Some(BoundLifetimes { 227fad3a1d3Sopenharmony_ci lifetimes: [ 228fad3a1d3Sopenharmony_ci GenericParam::Lifetime(LifetimeParam { 229fad3a1d3Sopenharmony_ci lifetime: Lifetime { 230fad3a1d3Sopenharmony_ci ident: "a", 231fad3a1d3Sopenharmony_ci }, 232fad3a1d3Sopenharmony_ci }), 233fad3a1d3Sopenharmony_ci ], 234fad3a1d3Sopenharmony_ci }), 235fad3a1d3Sopenharmony_ci path: Path { 236fad3a1d3Sopenharmony_ci segments: [ 237fad3a1d3Sopenharmony_ci PathSegment { 238fad3a1d3Sopenharmony_ci ident: "Trait", 239fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed { 240fad3a1d3Sopenharmony_ci args: [ 241fad3a1d3Sopenharmony_ci GenericArgument::Lifetime(Lifetime { 242fad3a1d3Sopenharmony_ci ident: "a", 243fad3a1d3Sopenharmony_ci }), 244fad3a1d3Sopenharmony_ci ], 245fad3a1d3Sopenharmony_ci }, 246fad3a1d3Sopenharmony_ci }, 247fad3a1d3Sopenharmony_ci ], 248fad3a1d3Sopenharmony_ci }, 249fad3a1d3Sopenharmony_ci }), 250fad3a1d3Sopenharmony_ci Token![+], 251fad3a1d3Sopenharmony_ci TypeParamBound::Lifetime { 252fad3a1d3Sopenharmony_ci ident: "static", 253fad3a1d3Sopenharmony_ci }, 254fad3a1d3Sopenharmony_ci ], 255fad3a1d3Sopenharmony_ci } 256fad3a1d3Sopenharmony_ci "###); 257fad3a1d3Sopenharmony_ci 258fad3a1d3Sopenharmony_ci let tokens = quote!(dyn 'a + Trait); 259fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 260fad3a1d3Sopenharmony_ci Type::TraitObject { 261fad3a1d3Sopenharmony_ci dyn_token: Some, 262fad3a1d3Sopenharmony_ci bounds: [ 263fad3a1d3Sopenharmony_ci TypeParamBound::Lifetime { 264fad3a1d3Sopenharmony_ci ident: "a", 265fad3a1d3Sopenharmony_ci }, 266fad3a1d3Sopenharmony_ci Token![+], 267fad3a1d3Sopenharmony_ci TypeParamBound::Trait(TraitBound { 268fad3a1d3Sopenharmony_ci path: Path { 269fad3a1d3Sopenharmony_ci segments: [ 270fad3a1d3Sopenharmony_ci PathSegment { 271fad3a1d3Sopenharmony_ci ident: "Trait", 272fad3a1d3Sopenharmony_ci }, 273fad3a1d3Sopenharmony_ci ], 274fad3a1d3Sopenharmony_ci }, 275fad3a1d3Sopenharmony_ci }), 276fad3a1d3Sopenharmony_ci ], 277fad3a1d3Sopenharmony_ci } 278fad3a1d3Sopenharmony_ci "###); 279fad3a1d3Sopenharmony_ci 280fad3a1d3Sopenharmony_ci // None of the following are valid Rust types. 281fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err(); 282fad3a1d3Sopenharmony_ci syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err(); 283fad3a1d3Sopenharmony_ci} 284fad3a1d3Sopenharmony_ci 285fad3a1d3Sopenharmony_ci#[test] 286fad3a1d3Sopenharmony_cifn test_trailing_plus() { 287fad3a1d3Sopenharmony_ci #[rustfmt::skip] 288fad3a1d3Sopenharmony_ci let tokens = quote!(impl Trait +); 289fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 290fad3a1d3Sopenharmony_ci Type::ImplTrait { 291fad3a1d3Sopenharmony_ci bounds: [ 292fad3a1d3Sopenharmony_ci TypeParamBound::Trait(TraitBound { 293fad3a1d3Sopenharmony_ci path: Path { 294fad3a1d3Sopenharmony_ci segments: [ 295fad3a1d3Sopenharmony_ci PathSegment { 296fad3a1d3Sopenharmony_ci ident: "Trait", 297fad3a1d3Sopenharmony_ci }, 298fad3a1d3Sopenharmony_ci ], 299fad3a1d3Sopenharmony_ci }, 300fad3a1d3Sopenharmony_ci }), 301fad3a1d3Sopenharmony_ci Token![+], 302fad3a1d3Sopenharmony_ci ], 303fad3a1d3Sopenharmony_ci } 304fad3a1d3Sopenharmony_ci "###); 305fad3a1d3Sopenharmony_ci 306fad3a1d3Sopenharmony_ci #[rustfmt::skip] 307fad3a1d3Sopenharmony_ci let tokens = quote!(dyn Trait +); 308fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 309fad3a1d3Sopenharmony_ci Type::TraitObject { 310fad3a1d3Sopenharmony_ci dyn_token: Some, 311fad3a1d3Sopenharmony_ci bounds: [ 312fad3a1d3Sopenharmony_ci TypeParamBound::Trait(TraitBound { 313fad3a1d3Sopenharmony_ci path: Path { 314fad3a1d3Sopenharmony_ci segments: [ 315fad3a1d3Sopenharmony_ci PathSegment { 316fad3a1d3Sopenharmony_ci ident: "Trait", 317fad3a1d3Sopenharmony_ci }, 318fad3a1d3Sopenharmony_ci ], 319fad3a1d3Sopenharmony_ci }, 320fad3a1d3Sopenharmony_ci }), 321fad3a1d3Sopenharmony_ci Token![+], 322fad3a1d3Sopenharmony_ci ], 323fad3a1d3Sopenharmony_ci } 324fad3a1d3Sopenharmony_ci "###); 325fad3a1d3Sopenharmony_ci 326fad3a1d3Sopenharmony_ci #[rustfmt::skip] 327fad3a1d3Sopenharmony_ci let tokens = quote!(Trait +); 328fad3a1d3Sopenharmony_ci snapshot!(tokens as Type, @r###" 329fad3a1d3Sopenharmony_ci Type::TraitObject { 330fad3a1d3Sopenharmony_ci bounds: [ 331fad3a1d3Sopenharmony_ci TypeParamBound::Trait(TraitBound { 332fad3a1d3Sopenharmony_ci path: Path { 333fad3a1d3Sopenharmony_ci segments: [ 334fad3a1d3Sopenharmony_ci PathSegment { 335fad3a1d3Sopenharmony_ci ident: "Trait", 336fad3a1d3Sopenharmony_ci }, 337fad3a1d3Sopenharmony_ci ], 338fad3a1d3Sopenharmony_ci }, 339fad3a1d3Sopenharmony_ci }), 340fad3a1d3Sopenharmony_ci Token![+], 341fad3a1d3Sopenharmony_ci ], 342fad3a1d3Sopenharmony_ci } 343fad3a1d3Sopenharmony_ci "###); 344fad3a1d3Sopenharmony_ci} 345fad3a1d3Sopenharmony_ci 346fad3a1d3Sopenharmony_ci#[test] 347fad3a1d3Sopenharmony_cifn test_tuple_comma() { 348fad3a1d3Sopenharmony_ci let mut expr = TypeTuple { 349fad3a1d3Sopenharmony_ci paren_token: token::Paren::default(), 350fad3a1d3Sopenharmony_ci elems: Punctuated::new(), 351fad3a1d3Sopenharmony_ci }; 352fad3a1d3Sopenharmony_ci snapshot!(expr.to_token_stream() as Type, @"Type::Tuple"); 353fad3a1d3Sopenharmony_ci 354fad3a1d3Sopenharmony_ci expr.elems.push_value(parse_quote!(_)); 355fad3a1d3Sopenharmony_ci // Must not parse to Type::Paren 356fad3a1d3Sopenharmony_ci snapshot!(expr.to_token_stream() as Type, @r###" 357fad3a1d3Sopenharmony_ci Type::Tuple { 358fad3a1d3Sopenharmony_ci elems: [ 359fad3a1d3Sopenharmony_ci Type::Infer, 360fad3a1d3Sopenharmony_ci Token![,], 361fad3a1d3Sopenharmony_ci ], 362fad3a1d3Sopenharmony_ci } 363fad3a1d3Sopenharmony_ci "###); 364fad3a1d3Sopenharmony_ci 365fad3a1d3Sopenharmony_ci expr.elems.push_punct(<Token![,]>::default()); 366fad3a1d3Sopenharmony_ci snapshot!(expr.to_token_stream() as Type, @r###" 367fad3a1d3Sopenharmony_ci Type::Tuple { 368fad3a1d3Sopenharmony_ci elems: [ 369fad3a1d3Sopenharmony_ci Type::Infer, 370fad3a1d3Sopenharmony_ci Token![,], 371fad3a1d3Sopenharmony_ci ], 372fad3a1d3Sopenharmony_ci } 373fad3a1d3Sopenharmony_ci "###); 374fad3a1d3Sopenharmony_ci 375fad3a1d3Sopenharmony_ci expr.elems.push_value(parse_quote!(_)); 376fad3a1d3Sopenharmony_ci snapshot!(expr.to_token_stream() as Type, @r###" 377fad3a1d3Sopenharmony_ci Type::Tuple { 378fad3a1d3Sopenharmony_ci elems: [ 379fad3a1d3Sopenharmony_ci Type::Infer, 380fad3a1d3Sopenharmony_ci Token![,], 381fad3a1d3Sopenharmony_ci Type::Infer, 382fad3a1d3Sopenharmony_ci ], 383fad3a1d3Sopenharmony_ci } 384fad3a1d3Sopenharmony_ci "###); 385fad3a1d3Sopenharmony_ci 386fad3a1d3Sopenharmony_ci expr.elems.push_punct(<Token![,]>::default()); 387fad3a1d3Sopenharmony_ci snapshot!(expr.to_token_stream() as Type, @r###" 388fad3a1d3Sopenharmony_ci Type::Tuple { 389fad3a1d3Sopenharmony_ci elems: [ 390fad3a1d3Sopenharmony_ci Type::Infer, 391fad3a1d3Sopenharmony_ci Token![,], 392fad3a1d3Sopenharmony_ci Type::Infer, 393fad3a1d3Sopenharmony_ci Token![,], 394fad3a1d3Sopenharmony_ci ], 395fad3a1d3Sopenharmony_ci } 396fad3a1d3Sopenharmony_ci "###); 397fad3a1d3Sopenharmony_ci} 398