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